C# 编译器错误地优化代码
我有一个在远程 Web 服务器上运行的 ASP.NET 应用程序,但我刚刚开始收到此错误:
Method not found: 'Void System.Collections.Generic.ICollection`1..ctor()'.
我反汇编了 DLL 中的代码,编译器似乎错误地优化了代码。 (请注意,Set 是一个实现一组唯一对象的类。它继承自 IEnumerable。)这行:
Set<int> set = new Set<int>();
编译成这行:
Set<int> set = (Set<int>) new ICollection<CalendarModule>();
CalendarModule 类是一个完全不相关的类! 有没有人注意到 .NET 以前错误地编译过这样的代码?
更新 #1: 这个问题似乎是由 Microsoft 的 ILMerge< 引入的/a> 工具。 我们目前正在研究如何克服它。
更新#2:到目前为止,我们找到了两种解决此问题的方法。 我们不太明白根本问题是什么,但是这两个方法都可以解决它:
关闭优化。
在另一台计算机上将程序集与 ILMerge 合并。
因此,我们想知道构建机器是否配置错误(考虑到我们已经使用该机器构建版本一年多了,这很奇怪)或者是否存在其他问题。
I have a ASP.NET application running on a remote web server and I just started getting this error:
Method not found: 'Void System.Collections.Generic.ICollection`1..ctor()'.
I disassembled the code in the DLL and it seems like the compiler is incorrectly optimizing the code. (Note that Set is a class that implements a set of unique objects. It inherits from IEnumerable.) This line:
Set<int> set = new Set<int>();
Is compiled into this line:
Set<int> set = (Set<int>) new ICollection<CalendarModule>();
The CalendarModule class is a totally unrelated class!! Has anyone ever noticed .NET incorrectly compiling code like this before?
Update #1: This problem seems to be introduced by Microsoft's ILMerge tool. We are currently investigating how to overcome it.
Update #2: We found two ways to solve this problem so far. We don't quite understand what the underlying problem is, but both of these fix it:
Turn off optimization.
Merge the assemblie with ILMerge on a different machine.
So we are left wondering if the build machine is misconfigured somehow (which is strange considering that we have been using the machine to build releases for over a year now) or if it is some other problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
哎哟。 如果这确实是 ILMerge 的错误,请根据您的发现及时更新本主题 — 我使用 ILMerge 作为构建 COM 互操作程序集的关键步骤。
Ouch. If this really is ILMerge at fault, please keep this topic up-to-date with your findings -- I use ILMerge as a key step in constructing a COM interop assembly.
最近是否将代码部署到该服务器? 有人会在您不知情的情况下推送构建吗? 您可以转到源代码管理、提取最新版本并复制该问题吗?
此时,根据给定的信息,我怀疑是编译器的问题。
Was code recently deployed to that server? Could someone have pushed a build without your knowledge? Can you go to source control, pull the latest, and duplicate the issue?
At this point, with the given information, I doubt it's the compiler.
我同意 Curt 和 Beds 的观点; 这听起来好像有什么严重错误。 优化器对我们所有人都有效,并且没有报告此类错误(据我所知) - 难道您实际上做错了什么?
旁注:我还想指出 .Net fx 3.5 中的
System.Collections.Generic.HashSet
其作用与Set<>
完全相同类应该。I agree with both Curt and Beds; this sounds like something is seriously wrong. The optimizer has worked for all of us and no such bugs have been reported (that I know of) - could it be that you are, in fact, doing something wrong?
Sidenote: I'd also like to point out
System.Collections.Generic.HashSet<T>
which is in .Net fx 3.5 and does exactly what aSet<>
class should.您确定您正在查看的程序集实际上是从相关源代码生成的吗? 你能用一个小测试用例重现这个问题吗?
编辑:如果您使用 Reflector,MSIL 到 C# 的转换可能不正确 - Reflector 在反编译时并不总是 100% 准确。 MSIL 是什么样的?
编辑 2: 嗯...我刚刚意识到这不可能是 Reflector 的错误,否则你不会在运行时收到该错误消息。
Are you sure that the assembly you're looking at was actually generated from the source code in question? Are you able to reproduce this problem with a small test case?
Edit: if you're using Reflector, it's possible that the MSIL to C# conversion isn't correct -- Reflector isn't always 100% accurate at decompiling. What does the MSIL look like?
Edit 2: Hmm... I just realized that it can't be Reflector at fault or you wouldn't have gotten that error message at runtime.
与 .Net 编译相比,这更有可能是反射工具的问题。 您收到的错误 - 在远程处理期间未找到构造函数很可能是序列化问题(所有可序列化类都需要无参数构造函数)。
从反射工具找到的代码更有可能抛出类型转换异常。
This is more likely to be an issue with the reflection tool than with the .Net compilation. The error you're getting - a constructor not found during remoting is most likely to be a serialisation issue (all serialisable classes need a parameterless constructor).
The code found from your reflection tool is more likely to throw a typecast exception.
啊,ILMerge - 你的问题中的额外信息确实有助于解决你的问题。 虽然我不会期望 .net 编译器会以这种方式失败,但我希望 ILMerge 偶尔会看到这种情况(考虑到它正在做什么)。
我的猜测是,您的两个程序集使用相同的优化“技巧”,一旦合并,您就会遇到冲突。
您向 Microsoft 提出了该错误吗?
同时,解决方法是将源程序集重新编译为单个程序集,从而无需使用 ILMerge。 由于 csproj 文件只是 XML 列表,因此它们基本上很容易合并,并且您可以将其自动化作为额外的 MSBuild 步骤。
Ahh, ILMerge - that extra info in your question really helps with your problem. While I wouldn't ever expect the .net compiler to fail in this way I would expect to occasionally see this sort of thing with ILMerge (given what it's doing).
My guess is that two of your assemblies are using the same optimisation 'trick', and once merged you get the conflict.
Have you raised the bug with Microsoft?
A workaround in the meantime is to recompile the assemblies from source as a single assembly, saving the need for ILMerge. As the csproj files are just XML lists they're basically easy to merge, and you could automate that as an extra MSBuild step.