C# 为什么这样做有效?

C# 为什么这样做有效?,c#,.net,generics,type-inference,C#,.net,Generics,Type Inference,为什么这样做有效?我不是在抱怨,只是想知道 void Test() { int a = 1; int b = 2; What<int>(a, b); // Why does this next line work? What(a, b); } void What<T>(T a, T b) { } C编译器支持泛型的类型推断,并且在使用var关键字时也很常见 这里int是从上下文a和b推断出来的,因此不需要。它使代码更

为什么这样做有效?我不是在抱怨,只是想知道

void Test()
{    
    int a = 1;
    int b = 2;

    What<int>(a, b);
    // Why does this next line work?
    What(a, b);
}

void What<T>(T a, T b)
{

}

C编译器支持泛型的类型推断,并且在使用var关键字时也很常见

这里int是从上下文a和b推断出来的,因此不需要。它使代码更干净,有时更易于阅读


有时,如果让编译器推断类型,代码的可读性可能会更高;有时,如果显式指定类型,代码的可读性可能会更高。这是对给定情况的判断调用。

编译器根据您传递的实际参数类型推断泛型类型参数

此功能使LINQ调用更加简单。您不需要写数字。选择i=>i.ToString,因为编译器从数字中推断int,从ToString中推断字符串。它可以工作,因为a和b是整数,所以编译器可以推断出什么的泛型类型参数

在C3中,编译器甚至可以在类型不匹配的情况下推断类型参数,只要扩大转换是有意义的。例如,如果c是长的,那么Whata,c将被解释为What


请注意,如果(比如)c是一个字符串,它将无法工作。

编译器足够聪明,能够找出泛型类型是“int”

它对泛型方法使用类型推断。注意,这在C2和3之间发生了变化。例如,这在C2中不起作用:

What("hello", new object());
。。。而在c3或c4中则是如此。在C2中,类型推断是基于每个参数执行的,结果必须精确匹配。在C3中,每个参数提供信息,然后将这些信息放在一起推断类型参数。C3还支持多阶段类型推断,编译器可以计算出一个类型参数,然后查看是否有关于其余类型的更多信息,例如,由于lambda表达式具有隐式参数类型。基本上,它一直在运行,直到它无法获得更多信息,或者它完成了——或者它看到了相互矛盾的信息。C语言中的类型推理不如算法强大,但它在其他方面工作得更好,尤其是它总是向前推进


有关更多信息,请参见C 3规范的第7.4.2节。

编译器可以推断T类型为int,因为这两个参数都被传递到int类型。您会注意到,许多Linq扩展都使用泛型定义为IEnumerable,但通常以您所展示的方式使用。

如果在C 3.0中如何工作的主题是你很感兴趣,这里有一段视频,是我在2006年第一次为C3.0设计该功能的时候解释的

另请参见我的博客的类型推断部分:


他没有使用var关键字。@SLaks:“也”常用seen@Dykam:他后来添加了这个短语。@Dykam:这说明当您使用泛型和使用var关键字时,C编译器支持泛型的类型推断。我更明确地澄清了我的意思,因此没有混淆的余地。也就是说,我的意思是,在这种情况下,@SLaks认为我的意思是,同时也是。@Dykam:在五分钟内所做的所有编辑都是合并的。因为他在给出答案后不到五分钟就编辑了它,所以编辑没有留下任何痕迹。另外请注意,如果你有两种不同的类型,都扩展了父类,并且你试图做a,b,其中a和b属于这两种不同的类型,它将无法推断出该类型是父类。@BlueRaja:事实上也是如此,因为在Dan的示例中,int和string都是Object的扩展。这里的设计原则是,当要求查找集合中的最佳成员时,C总是从集合中选择一个成员。它从不从集合外挑选成员。如果问到{老虎,长颈鹿}的最佳成员是什么,它没有说是动物,而是说没有最佳成员。链接断了,谷歌搜索他们包含的视频产生了死胡同。。。尽管文章年代久远,是否有机会转载?@Jazimov:我正在逐渐将内容转移到ericlippert.com;完成后,我将更新此处的链接。谢谢你的来信。