C# 为什么在另一个程序集中使用重载时,编译器有时要求您也引用子部件?

C# 为什么在另一个程序集中使用重载时,编译器有时要求您也引用子部件?,c#,.net,.net-assembly,overload-resolution,assembly-references,C#,.net,.net Assembly,Overload Resolution,Assembly References,关于下面提到的编译器错误以及如何解决它,有很多问题/答案,但这里的问题是询问一些见解,为什么在这种情况下需要这样做 为什么一个使用另一个被引用项目B的方法重载的项目a,在其重载签名之一中使用项目C的对象,要求您引用项目a中的项目C,即使您从未使用项目C中的对象 我想这一定与解决使用哪个重载有关,但我想了解其背后的概念 下面是一个例子: 将每个类放入自己的程序集中 //Put into Assembly C public class C {} //Put into assembly B, ref

关于下面提到的编译器错误以及如何解决它,有很多问题/答案,但这里的问题是询问一些见解,为什么在这种情况下需要这样做

为什么一个使用另一个被引用项目B的方法重载的项目a,在其重载签名之一中使用项目C的对象,要求您引用项目a中的项目C,即使您从未使用项目C中的对象

我想这一定与解决使用哪个重载有关,但我想了解其背后的概念

下面是一个例子:

将每个类放入自己的程序集中

//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类型“C”在未引用的程序集中定义。 必须添加对程序集“C”的引用,版本=1.0.0.0, 区域性=中性,PublicKeyToken=空'

在处理程序集B的重载时,您可以得到有趣的结果,因为并非每个组合都会产生错误:

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

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

另一个例子:

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

B.Test(""); //Call from assembly A compiles
public static void Test(string param, string param2){}
public static void Test(C param, int param2){}

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

还有一个例子:

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

B.Test(""); //Call from assembly A compiles
public static void Test(string param, string param2){}
public static void Test(C param, int param2){}

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

因此,这可能与重载解析的实现方式有关。然而,我不明白为什么编译器不能沿着依赖关系树向上运行,并要求我进行直接引用?重载解析不是必须在程序集B中完成吗?

出于好奇,我现在没有机会测试这一点,但是如果将
C
密封,您仍然会得到错误吗?(
公共密封C类{}
)支票制作
B
也密封。我知道,一旦引入密封类,逻辑会发生很多变化,因为编译器可以对您正在处理的对象进行更多假设。当您在主程序集的元数据中公开子程序集的类型时,就会发生这种情况。就像你把C作为论点的类型一样。编译器决定它需要更多地了解C来决定哪个重载是正确的。它过去对它比较松懈,不确切地知道发生了什么变化。可能是某种令人讨厌的情况,重载解析永远令人费解。@ScottChamberlain它并没有通过密封类来改变行为。@HansPassant似乎只要所用重载的参数数相等,编译器就会想要引用。我在c#文档中找不到描述这种行为的章节。