动态和其他类型的重载方法
Overloading Method with dynamic and other types
为什么我不能用 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.
那么编译器的困惑在哪里呢?为什么我不能有这样的重载?
来自 C# 5.0 规范,4.7 动态类型:
The type dynamic has special meaning in C#. Its purpose is to allow dynamic binding, which is described in detail in §7.2.2.
dynamic is considered identical to object except in the following respects:
• Operations on expressions of type dynamic can be dynamically bound (§7.2.2).
• Type inference (§7.5.2) will prefer dynamic over object if both are candidates.
Because of this equivalence, the following holds:
• There is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
• Implicit and explicit conversions to and from object also apply to and from dynamic.
• Method signatures that are the same when replacing dynamic with object are considered the same signature
事实上,一旦您的代码被编译,将 dynamic
作为参数的方法实际上与使用 object
声明相同的方法是一样的。只是在方法内部,可以动态使用 dynamic
参数(即使用 运行 时间绑定)。
因此,您的第一个示例方法对与您使用 object
.
参数类型声明这两个方法基本相同
在你的第二个例子中,就像你可以有一个参数为 object
而另一个参数为 string
的重载一样,你也可以使用 [=10 配对一个方法=] 使用 string
.
的同名方法
根据 C# 的重载解析规则(也在规范中),只要方法参数列表在允许选择一个方法重载作为 "best" 重载的方式上有所不同,就不会编译-会出现时间错误。在您的特定示例中,将 string
以外的任何内容传递给方法会自动排除使用 string
作为参数的方法。在您传递 string
的情况下,重载解析规则 select string
重载作为 "best" 重载,因此不会发生编译错误。
为什么我不能用 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.
那么编译器的困惑在哪里呢?为什么我不能有这样的重载?
来自 C# 5.0 规范,4.7 动态类型:
The type dynamic has special meaning in C#. Its purpose is to allow dynamic binding, which is described in detail in §7.2.2. dynamic is considered identical to object except in the following respects:
• Operations on expressions of type dynamic can be dynamically bound (§7.2.2).
• Type inference (§7.5.2) will prefer dynamic over object if both are candidates.
Because of this equivalence, the following holds:
• There is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
• Implicit and explicit conversions to and from object also apply to and from dynamic.
• Method signatures that are the same when replacing dynamic with object are considered the same signature
事实上,一旦您的代码被编译,将 dynamic
作为参数的方法实际上与使用 object
声明相同的方法是一样的。只是在方法内部,可以动态使用 dynamic
参数(即使用 运行 时间绑定)。
因此,您的第一个示例方法对与您使用 object
.
在你的第二个例子中,就像你可以有一个参数为 object
而另一个参数为 string
的重载一样,你也可以使用 [=10 配对一个方法=] 使用 string
.
根据 C# 的重载解析规则(也在规范中),只要方法参数列表在允许选择一个方法重载作为 "best" 重载的方式上有所不同,就不会编译-会出现时间错误。在您的特定示例中,将 string
以外的任何内容传递给方法会自动排除使用 string
作为参数的方法。在您传递 string
的情况下,重载解析规则 select string
重载作为 "best" 重载,因此不会发生编译错误。