假设我有两个C#方法的重载版本:
void Method( TypeA a ) { } void Method( TypeB b ) { }
我用以下方法调用该方法:
Method( null );
调用该方法的哪个重载?我该怎么做才能确保调用特定的重载?
这取决于TypeA
和TypeB
.
如果其中只有一个适用(例如,没有转换null
,TypeB
因为它是值类型但是TypeA
引用类型),那么将调用适用的那个.
否则它取决于TypeA
和之间的关系TypeB
.
如果存在隐式转换TypeA
,TypeB
但没有隐式转换TypeB
,TypeA
那么TypeA
将使用重载使用.
如果存在隐式转换TypeB
,TypeA
但没有隐式转换TypeA
,TypeB
那么TypeB
将使用重载使用.
否则,调用是不明确的,将无法编译.
有关详细规则,请参阅C#3.0规范的7.4.3.4节.
这是一个不模糊的例子.这里TypeB
派生的TypeA
,这意味着有一个从隐式转换TypeB
到TypeA
,而不是相反.因此使用过载TypeB
:
using System; class TypeA {} class TypeB : TypeA {} class Program { static void Foo(TypeA x) { Console.WriteLine("Foo(TypeA)"); } static void Foo(TypeB x) { Console.WriteLine("Foo(TypeB)"); } static void Main() { Foo(null); // Prints Foo(TypeB) } }
一般来说,即使面对其他模糊的调用,为了确保使用特定的重载,只需转换:
Foo((TypeA) null);
要么
Foo((TypeB) null);
请注意,如果这涉及声明类中的继承(即一个类重载由其基类声明的方法),那么您将遇到另一个问题,并且需要转换方法的目标而不是参数.
Jon Skeet给出了一个全面的答案,但从设计的角度来看,你不应该依赖于编译器规范的角落情况.如果没有别的,如果你在写它之前必须查看它的作用,下一个尝试阅读它的人也不会知道它做了什么.这是不可维护的.
为方便起见,重载是有的,并且具有相同名称的两个不同重载应该做同样的事情.如果这两种方法做了不同的事情,请重命名其中一种或两种.
对于重载方法而言,更常见的是具有不同数量的参数的变体,以及具有较少参数的过载以提供合理的默认值.
例如string ToString(string format, System.IFormatProvider provider)
,参数最多,
string ToString(System.IFormatProvider provider)
提供默认格式,并
string ToString()
提供默认格式和提供者,