为什么这样做?

时间:2010-05-04 13:38:51

标签: 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)
{

}

7 个答案:

答案 0 :(得分:18)

它起作用,因为ab是整数,因此编译器可以推断出What的泛型类型参数。

在C#3中,只要扩展转换有意义,编译器也可以推断类型参数,即使类型不匹配也是如此。例如,如果clong,那么What(a, c)将被解释为What<long>

请注意,如果cstring,则无效。

答案 1 :(得分:7)

C#编译器支持泛型的类型推断,如果使用var关键字,也常见。

此处int是从上下文(ab)推断的,因此不需要<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中的numbersstring中的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'