views:

815

answers:

6

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:

  1. Turn off optimization.

  2. 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.

+1  A: 

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.

Curt Hagenlocher
I have been unable to reproduce the problem with a smaller test case so far. In this case, the disassembly does appear to be correct. This is evidenced by the error I get referring to the ICollection constructor.
Kevin Albrecht
Does compiling without optimizations get rid of the error?
Mark Brackett
A: 

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.

Chuck
+1  A: 

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.

Keith
There is no serialization happening in the code.
Kevin Albrecht
Ok, but the exception throw would require the following code: new ICollection<yourType>()
Keith
+1  A: 

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 a Set<> class should.

configurator
I definitely agree with the "select isn't broken" school of thought, and the error probably isn't actually caused by a bad compiler, just something that makes it look like bad optimization.Thanks for the tip on HashSet<T>, unfortunately we are not on 3.5 yet, still on 2.0.
Kevin Albrecht
A: 

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.

Wayne
I'll let you know what we find.
Kevin Albrecht
+7  A: 

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.

Keith
Merging the .csproj files is a good idea, we might try that.
Kevin Albrecht
Does anyone have any good resources on how to compile multiple assemblies as one using the cs/vb compiler without ILMerge?
Lamar
@Lamar: I've already answered this question before. See http://stackoverflow.com/questions/1878807/vs2008-creating-single-dll-from-solution-with-many-projects/1879281#1879281
Roman Boiko