为什么编译器无法推断出对象数组类型?

我想知道为什么这是有效的:

object[] array = {"bla bla bla..", 23, true}; 

但这些不是:

 var array = {"bla bla bla..", 23, true }; var array2 = new [] {"bla bla bla..", 23, true }; 

在第二个例子中,为什么编译器不能根据数组初始值设定项中的值推断出数组类型? 这似乎很容易,特别是与generics类型推断相比。为了定义一个对象数组,为什么我必须明确指定数组类型?

 var array = new object[] { "bla bla bla..", 23, true }; 

因为数组中的类型不是特定object – 它们是3种不同的类型,它们都是对象的子类。

如果使用可在数组中推断的特定类型,编译器将推断该类型。 例如,这很好:

 var arr = new[] {3, 4, 5}; // Will correctly infer int[] 

请注意,这在C#语言规范的8.5.1中明确指出,该规范声明对于var受以下限制:

  • local-variable-declaration不能包含多个local-variable-declarators。
  • local-variable-declarator必须包含一个local-variable-initializer。
  • local-variable-initializer必须是表达式。
  • 初始化表达式必须具有编译时类型。
  • 初始化表达式不能引用声明的变量本身

在数组的情况下,有一个指定的例子:

 var y = {1, 2, 3}; // Error, array initializer not permitted 

至于new [] {"bla bla bla..", 23, true }; 例如,这在7.6.10中被调用。 在那里,这个例子:

 var d = new[] { 1, "one", 2, "two" }; // Error 

据说是一个错误,因为:

最后一个表达式导致编译时错误,因为int和string都不能隐式转换为另一个,因此没有最佳的常见类型。 在这种情况下,必须使用显式类型的数组创建表达式,例如将类型指定为object []。 或者,可以将其中一个元素强制转换为公共基类型,然后这将成为推断的元素类型

我会说它更像是一种安全function。 当然,编译器总是可以推断最小公分母object

但请考虑后果:在初始化您打算使用特定类型的数组时出错:(此处为int

 var array = {1, 2, 3, 4, 5, "6", 7, 8, 9}; 

通过复制和粘贴错误,您将"6"保留为字符串。 你没有抛出编译器错误,而是留下了一个意外的object[] ,这可能会导致你想要进入int[]

这不是Python – 我更喜欢通过节省几个字符进行显式输入。

据微软称

数组元素必须都是相同的类型或隐式转换为相同的类型[…]。 最佳类型必须是数组表达式中存在的类型之一。 元素不会转换为新类型,如object。

请参阅: 编译器错误CS0826