Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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.

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top