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工具引入的。我们目前正在研究如何克服它。
更新#2:到目前为止,我们发现了两种解决此问题的方法。我们不太了解潜在的问题是什么,但是这两个问题都可以解决:
- 关闭优化。
- 将组合与ILMerge合并到另一台计算机上。
因此,我们不知道构建机器是否以某种方式进行了错误配置(考虑到我们已经使用该机器构建发行版已有一年多的时间了,这很奇怪)还是其他问题。
解决方案
我们确定要查看的程序集实际上是从相关源代码生成的吗?我们可以用一个小的测试用例重现此问题吗?
编辑:如果我们使用的是Reflector,则从MSIL到Cconversion的可能不正确-Reflector在反编译时并不总是100%准确。 MSIL是什么样的?
编辑2:嗯...我只是意识到它不可能是Reflector的错误,否则我们将不会在运行时收到该错误消息。
最近是否将代码部署到该服务器?有人会在我们不知情的情况下推开建筑吗?我们可以使用源代码管理,获取最新版本并复制问题吗?
在这一点上,根据给定的信息,我怀疑它是编译器。
与.Net编译相比,反射工具更可能是一个问题。在远程处理期间找不到构造器的错误很可能是序列化问题(所有可序列化的类都需要无参数构造器)。
从反射工具中找到的代码更有可能引发类型转换异常。
我同意Curt和Beds的观点。听起来有些严重错误。该优化程序已经为我们所有人所用,没有(我知道)没有报告过此类错误,可能是我们实际上做错了什么吗?
旁注:我还想指出.System fx 3.5中的System.Collections.Generic.HashSet <T>
,它确实可以完成Set <>
类的工作。
哎哟。如果这确实是ILMerge的错,请将该主题与发现保持最新-我将ILMerge用作构建COM互操作程序集的关键步骤。
嗯,ILM合并问题中的额外信息确实可以解决问题。尽管我永远都不会指望.net编译器会以这种方式失败,但我希望偶尔会看到ILMerge出现这种情况(考虑到它在做什么)。
我的猜测是,两个程序集正在使用相同的优化"技巧",一旦合并,就会产生冲突。
我们是否向Microsoft提出了错误?
同时,一种解决方法是将源代码中的程序集重新编译为单个程序集,从而节省了对ILMerge的需求。由于csproj文件只是XML列表,因此它们基本上很容易合并,我们可以将其自动化作为额外的MSBuild步骤。