知道C#编译器可以推断信息量较少的信息,我感到很惊讶

时间:2014-06-09 19:46:26

标签: c# arrays

请考虑以下代码段,按时间顺序排列。无法编译注释语句。

    var data1 = new int[3] { 1, 2, 3 };
    var data2 = new int[] { 1, 2, 3 };

    var data3 = new[] { 1, 2, 3 };
    var data4 = new[] { 1, 2, 3.0f };

data3data4的简化是可以理解的。

    int[] data5 = { 1, 2, 3 };
    //var data6 = { 1, 2, 3 };

无法推断data6的声明是可以理解的。

    var data7 = new int[] { };
    //var data8 = new [] { }; 
    //int[] data9 = new [] { };

无法推断data8的声明也是可以理解的。

我不明白为什么data9无法编辑信息量较大的data10,而编制信息量较少的 int[] data10 = { }; //var data11 = { }; 可以编译。

data11

声明无法编译的{{1}}也是可以理解的。

2 个答案:

答案 0 :(得分:2)

C#是一种无法从上下文推断类型的语言类型。这意味着它只能从外部表达式中提取类型,反之亦然。

换句话说,您所显示的现象与以下情况下编译器无法选择正确的重载的事实相同:

int foo();
string foo();

string x = foo();

但是在下列情况下它可以选择正确的重载:

void bar(int x);
void bar(string x);

string x;
bar(x);

编辑: Servy评论说lambda表达式是该规则的一个例外。例如:

var a = new Func<int, bool>(a => a == 1);

编译器不能推断出“a =&gt; a == 1”的类型而不从上下文中推断它。

答案 1 :(得分:2)

存在new关键字的情况是通常的表达式,可以在需要表达式的任何上下文中自行使用。您可以将它们用于具有赋值的声明,但它们可以在其他上下文中使用,例如:

return new[] { 3 };

或:

Call(new[] { 3 });

等等。在这些new数组表达式中,类型必须从表达式本身清除。即使左侧有变量声明,也需要这样做。

案例data9因此,int[] data9 = new [] { };是非法的,因为表达式new[] { }是非法的。有点像:

object related9 = someBoolean ? "Yes" : new Exception();

这也是非法的,因为表达式someBoolean ? "Yes" : new Exception()本身是非法的,具有不兼容的类型。有一个object类型的声明,但这并不能使右侧合法。


示例data5data10显示了一个完全不相关的数组变量声明语法。

int[] data5 = { 1, 2, 3 };

此处=运算符的右侧是 表达式本身。此语法要求在=符号左侧显示带有显式类型的声明(因此data6不正常)。此语法与对象初始化程序集合初始化程序相关,并与C#语言一起引入,而new[] { ... }语法有点旧。


您应该看到this answer by Lippert,然后阅读官方C#语言规范。