C# 选择哪个C方法重载?
当两个重载都匹配时,为什么要调用泛型方法C# 选择哪个C方法重载?,c#,.net,generics,C#,.net,Generics,当两个重载都匹配时,为什么要调用泛型方法 public static void method1(object obj) { Console.WriteLine("Object"); } public static void method1<T>(T t) { Console.WriteLine("Type T"); } public static void Main(String args[]) { method1("xyz"); //Will print
public static void method1(object obj)
{
Console.WriteLine("Object");
}
public static void method1<T>(T t)
{
Console.WriteLine("Type T");
}
public static void Main(String args[])
{
method1("xyz"); //Will print "Type T";
}
这里不应该有任何冲突,对吗?通过选择最具体的重载来解决重载问题。在这种情况下,method1string比method1object更具体,因此选择了重载 详情请参阅 如果要选择特定重载,可以通过显式地将参数强制转换为所需的类型来实现。以下内容将调用method1object重载,而不是泛型重载:
method1((object)"xyz");
有些情况下,编译器不知道选择哪个重载,例如:
void method2(string x, object y);
void method2(object x, string y);
method2("xyz", "abc");
在这种情况下,编译器不知道选择哪个重载,因为两个重载都明显优于另一个重载,它不知道隐式向下转换到对象的字符串。因此,它将发出一个编译器错误。C将始终选择它所能选择的最具体的方法 编译时
method1("xyz");
它将查找具有指定名称的所有方法,然后尝试匹配参数。编译器将选择最具体的方法,在这种情况下,它更喜欢这种方法
method1(string s)
结束
请注意@Erik对编译器无法决定的示例的出色回答。因为您已经将T作为参数传入,所以不需要键入method1xyz;您可以直接使用method1xyz。Net已经知道它是一个字符串。如果你有方法1,那将是一个不同的故事 此外,由于method1object obj不接受字符串作为参数,因此它将首先支持泛型函数,因为它可以推断t。如果要将method1object obj更改为method1string obj,它将首先支持它,然后是泛型函数 方法重载是如何工作的 要查找调用方法的匹配签名,编译器将在类型层次结构中从下到上以及在虚拟表中进行搜索: 首先在类层次结构中, 然后在接口层次结构中。 因为类在接口上占优势 事实上,在成为接口类型之前,对象首先是类类型 非泛型签名优先于泛型,因为现实和事实优先于抽象,除非使用泛型参数允许调用更特殊类型的实例 将理论应用于问题 此电话:
method1("xyz");
与以下内容完美匹配:
void method1<T>(T t) { }
因为string是一个特殊的对象,它可以作为一个通用的参数来使用,从而更加精确
另一方面,如果你写:
void method1(string obj) { }
void method1<T>(T t) { }
第一种方法就是所谓的
案例研究
第一个调用调用第一个方法,因为实例是列表类型匹配的类型
第二个调用调用第二个方法,因为使用了侧转换实现
第三个调用调用第三个方法,因为指定了用于模板化的泛型参数
由于向下转换多态性,第四个调用调用第四个方法
它不查找method1string s,而是查找同名的方法,然后确定最佳匹配。@juharr如果你是对的,让我清理一下我的答案。你仍然需要删除method1string的部分。它更喜欢methodT而不是method1对象o@juharr对于这个特定的实例,您是正确的,但是我想更一般一些。实际上,是Ccompiler实现了泛型类型推断;它与.netSimilar to无关
void method1<T>(T t) { }
void method1(object obj)
void method1(string obj) { }
void method1<T>(T t) { }
var instance = new List<string>();
MyMethod(instance);
MyMethod((IEnumerable<string>) instance);
MyMethod<string>(instance);
MyMethod((object)instance);
void MyMethod<T>(List<T> instance) { }
void MyMethod<T>(IEnumerable<T> list) { }
void MyMethod<T>(T instance) { }
void MyMethod(object instance) { }