Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 选择哪个C方法重载?_C#_.net_Generics - Fatal编程技术网

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) { }