为什么这样做?我不是在抱怨,只是想知道。
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)
{
}
答案 0 :(得分:18)
它起作用,因为a
和b
是整数,因此编译器可以推断出What
的泛型类型参数。
在C#3中,只要扩展转换有意义,编译器也可以推断类型参数,即使类型不匹配也是如此。例如,如果c
是long
,那么What(a, c)
将被解释为What<long>
。
请注意,如果c
是string
,则无效。
答案 1 :(得分:7)
C#编译器支持泛型的类型推断,如果使用var关键字,也常见。
此处int
是从上下文(a
和b
)推断的,因此不需要<int>
。它使代码更清晰,有时更容易阅读。
如果您让编译器推断出类型,有时您的代码可能会更清晰,有时如果您明确指定类型可能会更清楚。这是对你的特定情况的判断。
答案 2 :(得分:7)
它使用通用方法的类型推断。请注意,这在C#2和3之间已经发生了变化。例如,这在C#2中不起作用:
What("hello", new object());
......而它会在C#3(或4)中出现。在C#2中,类型推断是基于每个参数执行的,结果必须完全匹配。在C#3中,每个参数都提供信息,然后将这些信息放在一起以推断类型参数。 C#3还支持多阶段类型推断,其中编译器可以计算出一个类型参数,然后查看它是否有关于其余参数的更多信息(例如,由于具有隐式参数类型的lambda表达式)。基本上它一直持续到它无法获得更多信息,或者它完成 - 或者它看到相互矛盾的信息。 C#中的类型推断并不像Hindley-Milner算法那样强大,但它在其他方面效果更好(特别是它总能推进进度)。
有关详细信息,请参阅C#3规范的第7.4.2节。
答案 3 :(得分:5)
编译器根据您传递的实际参数的类型推断泛型类型参数。
此功能使LINQ调用更加简单。 (您不需要编写numbers.Select<int, string>(i => i.ToString())
,因为编译器会推断int
中的numbers
和string
中的ToString
答案 4 :(得分:2)
编译器可以将类型T推断为int,因为传递给What()的两个参数都是int类型。您会注意到很多Linq扩展都使用泛型(如IEnumerable)定义,但通常以您显示的方式使用。
答案 5 :(得分:2)
如果您对C#3.0的工作方式很感兴趣,那么这是我在2006年首次为C#3.0设计该功能版本时的一段视频。
http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx
另请参阅我博客的“类型推断”部分:
http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx
答案 6 :(得分:1)
编译器非常聪明,可以确定泛型类型是'int'