C# 为什么编译器无法推断对象数组类型?
我想知道为什么这是有效的:C# 为什么编译器无法推断对象数组类型?,c#,arrays,type-inference,C#,Arrays,Type Inference,我想知道为什么这是有效的: object[] array = {"bla bla bla..", 23, true}; 但这些不是: var array = {"bla bla bla..", 23, true }; var array2 = new [] {"bla bla bla..", 23, true }; 在第二个示例中,为什么编译器不能根据数组初始值设定项中的值推断数组类型?这似乎很容易做到,尤其是与泛型类型推断相比。为了定义对象数组,为什么我必须显式指定数组类型 var arr
object[] array = {"bla bla bla..", 23, true};
但这些不是:
var array = {"bla bla bla..", 23, true };
var array2 = new [] {"bla bla bla..", 23, true };
在第二个示例中,为什么编译器不能根据数组初始值设定项中的值推断数组类型?这似乎很容易做到,尤其是与泛型类型推断相比。为了定义对象数组,为什么我必须显式指定数组类型
var array = new object[] { "bla bla bla..", 23, true };
因为数组中的类型不是特定的
object
——它们是3种不同的类型,都是object的子类
如果使用可以在数组中推断的特定类型,编译器将推断该类型。例如,这很好:
var arr = new[] {3, 4, 5}; // Will correctly infer int[]
请注意,C语言规范的8.5.1中明确指出了这一点,其中规定对于var
受以下限制:
- 局部变量声明不能包含多个局部变量声明器
- 局部变量声明器必须包含局部变量初始值设定项
- 局部变量初始值设定项必须是表达式李>
- 初始值设定项表达式必须具有编译时类型
- 初始值设定项表达式不能引用声明的变量本身
var y = {1, 2, 3}; // Error, array initializer not permitted
至于new[]{“blablabla..”,23,true}代码>示例,这在7.6.10中被调用。这里有一个例子:
var d = new[] { 1, "one", 2, "two" }; // Error
称为错误,因为:
最后一个表达式导致编译时错误,因为int和string都不能隐式转换为另一个,因此没有最佳公共类型。在这种情况下,必须使用显式类型的数组创建表达式,例如,将类型指定为object[]。或者,可以将其中一个元素转换为公共基类型,然后该基类型将成为推断的元素类型
据微软称
数组元素必须全部为同一类型或隐式转换为同一类型[…]。最佳类型必须是数组表达式中存在的类型之一。元素将不会转换为新类型,例如对象
请参阅:我认为这更像是一种安全功能。当然,编译器总是可以推断出最小的公分母,object
但是考虑后果:当初始化一个你想成为特定类型的数组时,你犯了一个错误:(这里是代码> INT/COME)
通过复制粘贴错误,您将“6”
保留为字符串。您没有抛出编译器错误,而是得到了一个意外的对象[]
,这可能会在您打算int[]
的过程中导致问题
这不是Python-我更喜欢显式键入,而不是节省几个字符。我想这与派生类有关,在这种情况下,编译器应该做什么,选择基类或说出它的对象数组?这似乎是合理的。但是如果我想将字符串、int和布尔值存储到同一个数组中,数组类型绝对应该是object,对吗?它不可能是另一种类型,因为它是唯一常见的类型。我想知道的是,为什么编译器不能看到它并为我推断出类型?或者可以将这些类型定义为另一个公共类型吗?我没有尝试过,但是如果我创建了一个自定义类型并定义了字符串、int和bool的隐式和显式转换,我可以将该类型用作公共类型吗?我在想,如果这是可能的话,那可能是一个很好的理由。@Selman22那很好,但你不能推断出它的类型。正如我所提到的,规范特别指出了这一点。我相信他们本可以把推断作为对象,但他们决定不这样做。只有编译器团队才能明确地说明为什么没有这样做,尽管我很高兴没有这样做,因为这是危险的,因为任何“奇数”都会回退到object。@Selman22-您可以尝试使用元组或编写自己的类,而不是使用字符串、int和boolean的object[]。
var array = {1, 2, 3, 4, 5, "6", 7, 8, 9};