得知c#编译器可以推断信息较少的声明,我感到很惊讶
本文关键字:声明 编译器 信息 得知 | 更新日期: 2023-09-27 18:07:41
按照时间顺序考虑下面的代码片段。注释的语句不能编译。
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 };
对data3
和data4
的简化是可以理解的。
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
也是可以理解的。
出现new
关键字的情况是通常的表达式,可以在任何需要表达式的上下文中自行使用。您可以将它们用于具有赋值的声明,但它们可以用于其他上下文中,例如:
return new[] { 3 };
或:
Call(new[] { 3 });
等等。在这些new
数组表达式中,类型必须与表达式本身明确。即使在左侧有变量声明,也需要这样做。
data9
和int[] data9 = new [] { };
是不合法的,因为表达式new[] { }
是不合法的。它有点像:
object related9 = someBoolean ? "Yes" : new Exception();
也是非法的,因为表达式someBoolean ? "Yes" : new Exception()
本身是非法的,具有不兼容的类型。这里有一个类型为object
的声明,但这并不意味着右边是合法的。
示例data5
和data10
显示了一种完全不相关的数组变量声明语法。
int[] data5 = { 1, 2, 3 };
这里,=
操作符的右边是,而不是本身是表达式。这种语法要求在=
符号的左边有一个显式类型的声明(所以data6
是不可以的)。该语法与对象初始化器和集合初始化器相关,并在c#语言中与它们一起引入,而new[] { ... }
语法则稍早一些。
你应该看看Lippert的回答,然后阅读官方的c#语言规范
c#是一种不能从上下文推断类型的语言。这意味着它只能从表达式外部提取类型,反之亦然。
换句话说,您所显示的现象与以下情况下编译器无法选择正确的重载相同:
int foo();
string foo();
string x = foo();
但是,在下列情况下,它可以选择正确的重载:
void bar(int x);
void bar(string x);
string x;
bar(x);
Edit: Servy注释说lambda表达式是该规则的例外。例如:
var a = new Func<int, bool>(a => a == 1);
编译器不能推断"a => a == 1"的类型,除非从上下文中推断。