6

There are quite a few questions/answers about the compiler error mentionend below and how to resolve it, but the question here is asking about some insights why in this case this is required.

Why does a project A which uses an overload of a method of another referenced project B, which uses an object of project C in one of it's overloaded signatures require, that you reference project C from project A, even if you never use the object from project C?

I guess it must have to do with the resolving of which overload to use, but I'd like to understand the concept behind.

Here's an example:

Put each of the classes in an own assembly.

//Put into Assembly C
public class C {}

//Put into assembly B, reference C
public class B
{
    public static void Test(string param) //Simple method with one string parameter
    {
    }

    public static void Test(C param) //Overload which uses type of assembly C   
    {
    }
}

//Call placed in method of assembly A which uses and references only assembly B, but not C
B.Test("TestString"); // fails to compile, CS0012

CS0012 The type 'C' is defined in an assembly that is not referenced. You must add a reference to assembly 'C, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

You can get interesting results when playing around with the overloads of assembly B, because not every combination does produce the error:

public static void Test(){}
public static void Test(C param){}

B.Test(); //Call from assembly A compiles


Another example:

public static void Test(string param){}
public static void Test(C param, int param2){}

B.Test(""); //Call from assembly A compiles


Yet another example:

public static void Test(string param, string param2){}
public static void Test(C param, int param2){}

B.Test("",""); //Fails, CS0012

So this propably has to do how the overload resolution is done. However, I don't understand why the compiler can't just work it's way up the dependency tree and requires me to do a direct reference? Wouldn't the overload resolution have to be done in assembly B anyways?

Marwie
  • 3,177
  • 3
  • 28
  • 49
  • Out of curiosity, and I don't have the chance to test this right now, but if you make `C` sealed do you still get the error? (`public sealed class C {}`) Check making `B` sealed too. I know a lot of logic changes once you introduce sealed classes because the compiler is allowed to make more assumptions about what the object you are working with ***is not***. – Scott Chamberlain Nov 20 '15 at 17:37
  • 3
    It happens when you expose types from the sub-assembly in the metadata of your primary assembly. Like you did by making C the type of the argument. The compiler decides that it needs to know more about C to decide which overload is correct. It used to be more lax about it, not exactly sure what changed. Probably some kind of nasty corner-case, overload resolution is forever convoluted. – Hans Passant Nov 20 '15 at 17:44
  • @ScottChamberlain it did not change the behaviour by making the class sealed. – Marwie Nov 23 '15 at 07:43
  • @HansPassant it seems that as soon as the number of parameters of a used overload is equal, the compiler wants to have the reference. I couldn't find the chapter in the c# documentation which describes this behaviour. – Marwie Nov 23 '15 at 07:43

0 Answers0