为什么我不能使用dynamic
和object
参数重载方法。
void Method(dynamic arg) // Member with same signature is already declared
{
Console.WriteLine("Dynamic");
}
void Method(object arg) // Member with same signature is already declared
{
Console.WriteLine("Not Dynamic");
}
但是我可以使用dynamic
和其他类型的 对象重载方法,或者自动动态。
void Method(dynamic arg)
{
Console.WriteLine("Dynamic");
}
void Method(string arg)
{
Console.WriteLine("Not Dynamic");
}
正如您在第一个示例中所看到的,编译器无法区分两个重载。
我认为第二个例子也不应该工作,因为字符串可以发送到两个重载。但是编译器更喜欢用已知类型调用重载。
我已经做了一些测试,看看它是如何运作的。
Method(""); // Prints: Not Dynamic
Method((dynamic)""); // Prints: Not Dynamic
Method(null); // Prints: Not Dynamic
Method(???); // Dynamic for any other type except string and null.
考虑第一个示例作品,编译器会这样决定:
Method(new object());// Prints: Not Dynamic
Method((object)5); // Prints: Not Dynamic
Method(???); // Prints: Dynamic for any other type except object and null.
那么编译器的混淆在哪里?为什么我不能有这样的超载?
答案 0 :(得分:2)
从C#5.0规范中, 4.7动态类型:
类型动态在C#中具有特殊含义。其目的是允许动态绑定,这在第7.2.2节中有详细描述。 动态被认为与对象相同,但以下方面除外:
•动态类型表达式的操作可以动态绑定(第7.2.2节)。
•如果两者都是候选者,类型推断(第7.5.2节)将更喜欢动态而不是对象。
由于这种等价性,以下内容如下:
•对象和动态之间存在隐式标识转换,并且在用对象替换动态时,构造类型之间存在相同的转换
•与对象之间的隐式和显式转换也适用于动态和来自动态。
•将对象替换为动态时相同的方法签名被视为相同的签名
事实上,一旦编译了代码,以dynamic
作为参数的方法实际上与使用object
声明相同方法的方法相同。只是在方法内部,dynamic
参数可以动态使用(即使用运行时绑定)。
因此,您的第一个示例方法对与使用参数类型object
声明两个方法的方法基本相同。
在你的第二个例子中,就像你可以有一个参数为object
而另一个参数为string
的重载一样,你也可以使用dynamic
配对一个方法使用string
的同名方法。
根据C#的重载决策规则(也在规范中),只要方法参数列表的方式不同,允许选择一个方法重载作为“最佳”重载,就不会发生编译时错误。在您的特定示例中,将string
以外的任何内容传递给该方法会自动将string
作为参数排除方法。在传递string
的情况下,重载决策规则选择string
重载作为“最佳”重载,因此不会发生编译错误。