views:

3005

answers:

10

(I spent a few hours yesterday fighting with this problem, couldn't find any solutions here or anywhere else, so I'm adding this here for anyone else who has this problem.)

I've got a very weird bug on our test machine. The error is:

System.TypeLoadException: Method 'SetShort' in type 'DummyItem' from assembly 'ActiveViewers (...)' does not have an implementation.

I just can't understand why - I'm looking at my code, SetShort is there in the DummyItem class, and I've even recompiled a version with writes to the event log just to make sure that it's not a deployment/versioning issue. The weird thing is that the calling code doesn't even call the SetShort method...

+23  A: 

NOTE - If this answer doesn't help you, please take the time to scroll down through the other answers that people have added since.

Short answer

This can happen if you add a method to an interface in one assembly, and then to an implementing class in another assembly, but you rebuild the implementing assembly without referencing the new version of the interface assembly.

In this case, DummyItem implements an interface from another assembly. The SetShort method was recently added to both the interface and the DummyItem - but the assembly containing DummyItem was rebuilt referencing the previous version of the interface assembly. So the SetShort method is effectively there, but without the magic sauce linking it to the equivalent method in the interface.

Long answer

If you want to try reproducing this, try the following:

  1. Create a class library project: InterfaceDef, add just one class, and build:

    public interface IInterface
    {
        string GetString(string key);
        //short GetShort(string key);
    }
    
  2. Create a second class library project: Implementation (with separate solution), copy InterfaceDef.dll into project directory and add as file reference, add just one class, and build:

    public class ImplementingClass : IInterface
    {
        #region IInterface Members
        public string GetString(string key)
        {
            return "hello world";
        }
    
    
    
    //public short GetShort(string key)
    //{
    //    return 1;
    //}
    #endregion
    
    }
  3. Create a third, console project: ClientCode, copy the two dlls into the project directory, add file references, and add the following code into the Main method:

     IInterface test = new ImplementingClass();
     string s = test.GetString("dummykey");
     Console.WriteLine(s);
     Console.ReadKey();
    
  4. Run the code once, the console says "hello world"

  5. Uncomment the code in the two dll projects and rebuild - copy the two dlls back into the ClientCode project, rebuild and try running again. TypeLoadException occurs when trying to instantiate the ImplementingClass.

Benjol
Nice example of answering your own question to persist experience.
Michael Petrotta
You might need to add that the Console app should be rebuilt with the new DLLs as reference. Merely copying the DLL won't work and that could be due to version mismatch (i.e after you compile the source DLL the version will change). Is that fair understanding?
shahkalpesh
@shahkalpesh good point - for me 'running again' implied F5. I've updated the answer. Of course all this wouldn't have happened with a decent source control tool, but don't get me started on that subject...
Benjol
Hmm, it looks like Microsoft's error message has an error in it - it's saying that a method of class "DummyItem" doesn't have an implementation, which is patently false.... really the problem is that a method of the interface isn't implemented BY DummyItem.
Qwertie
+4  A: 

In addition to what the asker's own answer already stated, it may be worth noting the following. The reason this happens is because it is possible for a class to have a method with the same signature as an interface method without implementing that method. The following code illustrates that:

public interface IFoo
{
    void DoFoo();
}

public class Foo : IFoo
{
    public void DoFoo() { Console.WriteLine("This is _not_ the interface method."); }
    void IFoo.DoFoo() { Console.WriteLine("This _is_ the interface method."); }
}

Foo foo = new Foo();
foo.DoFoo();               // This calls the non-interface method
IFoo foo2 = foo;
foo2.DoFoo();              // This calls the interface method
Timwi
A: 

I got this in a WCF service due to having an x86 build type selected, causing the bisn to live under bin\x86 instead of bin. Selecting Any CPU caused the recompiled DLLs to go to the correct locations (I wont go into detail as to how this happened in the first place).

Ruben Bartelink
+3  A: 

I got this when my application didn't have a reference to another assembly defining a class that the method in the error message used. Running PEVerify gave more helpful error: "The system cannot find the file specified."

silent tone
+2  A: 

The other time you can get this error is if you have an incorrect version of a signed assembly. It's not the normal symptom for this cause, but here was the scenario where I got it

  • an asp.net project contains assembly A and assembly B, B is strongly named

  • assembly A uses Activator.CreateInstance to load assembly C (i.e. there is no reference to C which is built separately)

  • C was built referencing an older version of assembly B than is currently present

hope that helps someone - it took me ages to figure this out.

Tim
A: 

FWIW, I got this when there was a config file that redirected to a non-existant version of a referenced assembly. Fusion logs for the win!

Tilman
+1  A: 

I came across the same message and here is what we have found: We use third party dlls in our project. After a new release of those was out we changed our project to point to the new set of dlls and compiled successfully.

The exception was thrown when I tried to instatiate one of the their interfaced classes during run time. We made sure that all the other references were up to date, but still no luck. We needed a while to spot (using the Object Browser) that the return type of the method in the error message was a completely new type from a new, unreferenced assembly.

We added a reference to the assembly and the error disappeared.

  • The error message was quite misleading, but pointed more or less to the right direction (right method, wrong message).
  • The exception ocurred even though we did not use the method in question.
  • Which leads me to the question: If this exception is thrown in any case, why does the compiler not pick it up?
Ben
That IS weird..
Benjol
+1  A: 

I had this error too, it was caused by an Any CPU exe referencing Any CPU assemblies that in turn referenced an x86 assembly.

The exception complained about a method on a class in MyApp.Implementations (Any CPU), which derived MyApp.Interfaces (Any CPU), but in fuslogvw.exe I found a hidden 'attempt to load program with an incorrect format' exception from MyApp.CommonTypes (x86) which is used by both.

Richard Dingwall
A: 

I got this with a "diamont" shaped project dependency:

Project A uses Project B and Project D Project B uses Project D

I recompiled project A but not Project B, which allowed Project B to "inject" the old version of the Project D dll

Serge Desmedt
Yeah, I like to think of that as the [Renault](http://images.google.com/images?q=renault+logo) problem
Benjol
A: 

I also got this error when I had previously enabled Code Coverage during unit testing for one of the assemblies. For some reason Visual Studio "buffered" the old version of this particular DLL even though I had updated it to implement a new version of the interface. Disabling Code Coverage got rid of the error.

Kyberias