【问题标题】:Why does this work?为什么这行得通?
【发布时间】:2010-05-04 13:38:50
【问题描述】:

为什么会这样?我不是在抱怨,只是想知道。

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# .net generics type-inference


    【解决方案1】:

    因为ab 是整数,所以编译器可以推断What 的泛型类型参数。

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

    请注意,如果 cstring,它将不起作用。

    【讨论】:

    • 还要注意,如果你有两种不同的类型,它们都扩展Parent,并且你尝试做What(a, b)(其中 a 和 b 属于这两种不同的类型),它不会知道推断类型为Parent
    • @BlueRaja:实际上情况相同,因为在 Dan 的示例中,int 和 string 都是 Object 的扩展。这里的设计原则是,当被要求找到集合中的“最佳”成员时,C# 总是从集合中挑选一个成员。它从不从集合外挑选成员。如果问{Tiger, Giraffe} 的最佳成员是什么,它不会说“动物”,而是说没有最佳成员。
    【解决方案2】:

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

    这里int 是从上下文(ab)推断出来的,因此不需要&lt;int&gt;。它有时使代码更清晰,更易于阅读。

    有时,如果您让编译器推断类型,您的代码可能会更清晰易读,有时如果您明确指定类型,则可能会更清晰。这是对您特定情况的判断。

    【讨论】:

    • 他没有使用var关键字。
    • @SLaks: "'也' 常见的"
    • @Dykam:他后来添加了这句话。
    • @Dykam:当您使用泛型和使用 var 关键字时,C# 编译器支持泛型的类型推断。我更具体地澄清了,所以我的意思没有混淆的余地。 IE。我的意思是“并且在这种情况下”,@SLaks 认为我的意思是“并且同时”。
    • @Dykam:在五分钟内进行的所有编辑都被合并。由于他在给出答案后不到五分钟就编辑了它,因此编辑没有留下任何痕迹。
    【解决方案3】:

    它对泛型方法使用类型推断。请注意,这在 C# 2 和 3 之间发生了变化。例如,这在 C# 2 中是行不通的:

    What("hello", new object());
    

    ... 而它会在 C# 3(或 4)中。在 C# 2 中,类型推断是基于每个参数执行的,结果必须完全匹配。在 C# 3 中,每个参数都提供信息,然后将这些信息放在一起以推断类型参数。 C# 3 还支持 multi-phase 类型推断,其中编译器可以计算出一个类型参数,然后查看它是否有关于其余部分的更多信息(例如,由于具有隐式参数类型的 lambda 表达式)。基本上它会一直运行,直到它无法获得更多信息,或者它完成 - 或者它看到相互矛盾的信息。 C# 中的类型推断不如 Hindley-Milner 算法强大,但在其他方面效果更好(特别是它总是向前推进)。

    有关详细信息,请参阅 C# 3 规范的第 7.4.2 节。

    【讨论】:

      【解决方案4】:

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

      此功能使 LINQ 调用更加简单。 (你不需要写numbers.Select&lt;int, string&gt;(i =&gt; i.ToString()),因为编译器从numbers推断int和从ToString推断string

      【讨论】:

        【解决方案5】:

        编译器可以将类型 T 推断为 int,因为传递给 What() 的两个参数都是 int 类型。您会注意到很多 Linq 扩展都是用泛型定义的(如 IEnumerable),但通常以您展示的方式使用。

        【讨论】:

          【解决方案6】:

          如果您对 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

          【讨论】:

          • 链接被破坏并在谷歌上搜索它们包含的视频产生了死胡同......尽管帖子的年代久远,还有机会重新发布吗?
          • @Jazimov:我正在逐渐将内容移至 ericlippert.com;完成后我会在这里更新链接。感谢您的来信。
          【解决方案7】:

          编译器足够聪明,可以确定泛型类型是 'int'

          【讨论】:

            猜你喜欢
            • 2011-11-20
            • 1970-01-01
            • 2016-04-28
            • 1970-01-01
            • 1970-01-01
            • 2014-12-02
            • 2014-04-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多