具有动态和其他类型的重载方法

时间:2015-07-13 02:26:54

标签: c# object dynamic overloading

为什么我不能使用dynamicobject参数重载方法。

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.

那么编译器的混淆在哪里?为什么我不能有这样的超载?

1 个答案:

答案 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重载作为“最佳”重载,因此不会发生编译错误。