C#:将null传递给重载的方法 – 调用哪个方法?
假设我有两个C#方法的重载版本:
void Method( TypeA a ) { } void Method( TypeB b ) { }
我将这个方法称为:
Method( null );
该方法的哪个重载被调用? 我能做些什么来确保一个特定的超载被称为?
这取决于TypeA
和TypeB
。
- 如果其中只有一个是适用的(例如,没有从
null
到TypeB
转换,因为它是一个值types,但是TypeA
是一个引用types),那么将调用适用的。 - 否则,它取决于
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);
请注意,如果这涉及到声明类中的inheritance(即,一个类重载由其基类声明的方法),那么您将遇到另外一个问题,您需要转换方法的目标而不是参数。
Jon Skeet给出了一个全面的答案,但是从devise的angular度来看,你不应该依赖于编译器规范的angular落案例。 如果没有其他的东西,如果你在写它之前必须查看它做了什么,下一个尝试阅读它的人将不知道它做了什么。 这是不可维护的。
重载是为了方便,两个同名的重载应该做同样的事情。 如果这两种方法做不同的事情,重命名一个或两个。
对于重载方法来说,更多的variables具有不同数量的参数,而对于具有较less参数的重载来提供合理的默认值更为常见。
例如string ToString(string format, System.IFormatProvider provider)
具有最多的参数,
string ToString(System.IFormatProvider provider)
提供默认格式,并
string ToString()
提供一个默认的格式和提供者,
Jon Skeet已经回答了默认情况下select哪个重载,但是如果你想确保调用特定的重载,通常使用命名参数比cast更好。
如果你有:
void Method( TypeA a ) { } void Method( TypeB b ) { }
你可以调用Method(a: null);
或Method(b: null);
ambigous电话。 (编译时错误)。
一个简单的解决scheme是创build另一个签名为:
void Method() { }
或者更好地更新其中一种方法的签名为:
void Method( TypeB b = null ) { }
然后像这样调用它:
Method();
在编译时, null
的值是无types的,所以编译器不能和其中一个方法签名匹配。 在运行时,任何可能parsing为null
variables仍将被键入,因此不会导致问题。