无法确定条件表达式的类型?

Eri*_*fer 5 .net c# compiler-construction

我刚刚遇到这个(编写代码来演示"问题"):

public ICollection<string> CreateCollection(int x)
{
    ICollection<string> collection = x == 0 
                                   ? new List<string>() 
                                   : new LinkedList<string>();
    return collection;
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

Fehler CS0173:Der Typ des bedingten Ausdrucks kann nicht bestimmt werden,weil keine implizite Konvertierung zwischen"System.Collections.Generic.List"und"System.Collections.Generic.LinkedList"erfolgt.

其翻译大致为:

无法确定条件运算符的类型,因为List和LinkedList之间没有隐式转换.

我可以看到为什么编译器抱怨,但是,嘿,来吧.它试图发挥愚蠢.我可以看到两个表达式不是同一类型,而是有一个共同的祖先,作为奖励,左侧的类型也是共同的祖先.我相信编译器也可以看到它.如果左侧被声明为,我可以理解错误var.

我在这里错过了什么?

编辑:

我接受詹姆斯·冈特的解释.也许只是为了说清楚.我可以很好地阅读编译器规范.我想了解原因.为什么有人决定以这种方式编写规范.这种设计背后必然有一个原因.根据詹姆斯的说法,设计原则是"毫无意外".此外,CodeInChaos还解释了如果编译器试图从常见的祖先中推断出类型,您可能遇到的惊喜.

Jam*_*unt 10

表达式(a?b:c)必须解析为一种类型.类型将是b或c的类型.如果它们不同(并且没有从一个到另一个的隐式转换),则编译器在编译时不知道这是哪种类型.

您可能会说它应该推断出存在共同的根类型,但总有一个共同的根类型(例如Object).

通常,C#编译器不会尝试猜测你的意思.如果要使用公共根类型,则将b和c强制转换为该类型.

这样的逻辑运行,整个C#的设计,它是偶尔有点讨厌,但远远更多的时候它阻止你犯错.

  • 不,它不猜.var只能在已知RHS类型时使用.var不会使编译器做任何不同的事情 - 它只会节省您的输入. (9认同)
  • Eric Lippert的博客定期提出这类问题.在一天结束时,这是C#的核心设计原则,有时他称之为"没有惊喜". (3认同)