假设我有一个类(ClassA
),其中包含一个调用另一个类的构造函数的方法,如下所示:
public class ClassA
{
public void CallClassBConstructor()
{
using(ClassB myB = new ClassB()) {...}
}
}
班级ClassB
如下所示:
public class ClassB : IDisposable
{
public ClassB(){}
public ClassB(string myString){}
public ClassB(ClassC myC){}
public void Dispose() {...}
}
...... ClassC
更简单:
public class ClassC{}
如果我将这些类放在自己的程序集中并编译整个解决方案,我就不会出现任何错误。但是如果我用这个替换using语句:
using(ClassB myB = new ClassB("mystring")){...}
我收到编译错误,要求我在[mynamespace].ClassC
中添加对ClassA
的引用。因为我根本没有调用ClassB(ClassC myC)
这对我没有意义 - 为什么我必须包括其他构造函数的类型,无论我是否使用它们?如果ClassC
包含在许可或难以获取的程序集中会怎样?这是开发人员应该避免的错误设计的一个例子,还是我在这里遗漏了一些东西?
答案 0 :(得分:9)
调用ClassB
构造函数时,它与方法重载解析有关。
当您调用没有参数的构造函数时,没有争用。只有一个候选人,所以选择它。在这种情况下,ClassA
无需引用ClassC
。
但是,当您使用一个参数调用构造函数时,则在开始时,两个单参数构造函数都是候选者。为了解决此调用,编译器需要了解ClassC
。如您所知,ClassC
可以包含隐式转换运算符,例如。
(当然我们知道在这个特定的例子中,这样一个隐式转换运算符无论如何都不会触发,因为有一个完美匹配需要一个字符串 - 但方法重载决策规则是这样定义的,以使它们非常好 - 定义和可预测。想象一下,它的设计方式是添加引用可能会导致代码突然调用不同的构造函数重载。)
答案 1 :(得分:1)
要解决构造函数重载,编译器需要知道所涉及的类型。即它需要知道ClassC
才能为ClassB
选择正确的构造函数重载。
答案 2 :(得分:1)
这是因为ClassC
放在一个单独的程序集中,它是ClassB
的公共接口的一部分,因为它是其中一个构造函数的参数。您必须引用此类型的包含程序集,否则编译器不知道如何解析类型信息。在这种特定情况下,编译器必须解析所有构造函数重载中的所有参数类型,以便它可以选择正确的参数类型,但这本身不是成员重载问题。只要编译器必须解析类型信息,就会发生这种情况它也可能发生在返回类型上。