简体   繁体   English

为什么编译器没有将var []转换为c#中的object []?

[英]Why doesn't the compiler convert var[] to object[] in c#?

There is no difference between these two lines, because the compiler, in the second line, understands that it is an array of type int . 这两行之间没有区别,因为第二行中的编译器理解它是int类型的数组。

var x = new int[] { 1, 2, 3 };   //Fine, x is int[]
var x = new [] { 1, 2, 3 };      //Fine, x is int[]

But why can't I do this with different types? 但为什么我不能用不同类型做到这一点? Why doesn't the compiler convert my variable to type object ? 为什么编译器不将我的变量转换为类型对象

var x = new object[] { 1, "df", 5 };   //Fine, x is object[]
var x = new [] { 1, "df", 5 };         //Error! "No best type found for implicity-typed-array"

EDIT: 编辑:

Thanks for all your answers. 谢谢你的所有答案。 But I still wonder, what are the pros and cons to make all expressions that the compiler can't convert to type object ? 但我仍然想知道,使编译器无法转换为类型object所有表达式的优缺点是什么? (Because I use var notation which means that it can't be any type. I understand like this.) Why doesn't the compiler find the nearest type of the array members by going up the inheritance tree? (因为我使用var表示法,这意味着它不能是任何类型。我这样理解。)为什么编译器不通过继承树找到最近类型的数组成员?

The new [] notation is for saving you to type an explicit type of the array members (or allowing you to create arrays where its elements have an anonymous type), but its type inference is limited in that all elements must share the same type or be implicitly convertible to a common type shared by at least one member. new []表示法用于保存您键入数组成员的显式类型(或允许您创建其元素具有匿名类型的数组),但其类型推断受到限制,因为所有元素必须共享相同的类型或可隐式转换为至少一个成员共享的公共类型。 See C# Specification, section 7.6.10.4: 参见C#规范,第7.6.10.4节:

An array creation expression of the third form is referred to as an implicitly typed array creation expression. 第三种形式的数组创建表达式称为隐式类型的数组创建表达式。 It is similar to the second form, except that the element type of the array is not explicitly given, but determined as the best common type (§7.5.2.14) of the set of expressions in the array initializer. 它与第二种形式类似,不同之处在于未明确给出数组的元素类型,而是确定为数组初始值设定项中表达式集的最佳公共类型(第7.5.2.14节)。

The following are examples of implicitly typed array creation expressions: 以下是隐式类型化数组创建表达式的示例:

 var a = new[] { 1, 10, 100, 1000 }; // int[] var b = new[] { 1, 1.5, 2, 2.5 }; // double[] var c = new[,] { { "hello", null }, { "world", "!" } }; // string[,] var d = new[] { 1, "one", 2, "two" }; // Error 

The last expression causes a compile-time error because neither int nor string is implicitly convertible to the other, and so there is no best common type. 最后一个表达式导致编译时错误,因为intstring都不能隐式转换为另一个,因此没有最佳的常见类型。 An explicitly typed array creation expression must be used in this case, for example specifying the type to be object[] . 在这种情况下,必须使用显式类型的数组创建表达式,例如将类型指定为object[] Alternatively, one of the elements can be cast to a common base type, which would then become the inferred element type. 或者,可以将其中一个元素强制转换为公共基类型,然后将其作为推断元素类型。

Key point here is that the “best common type” can only be one of the types already present. 这里的关键点是“最常见的类型”只能是已经存在的类型之一。 As Damien_The_Unbeliever pointed out in a comment: “As Mr. Lippert is fond of pointing out around inference, whenever it's looking for a best common type, it will only return one of the types that is already present - it doesn't go hunting for the most-derived common ancestor.” . 正如Damien_The_Unbeliever在评论中所指出的那样: “正如Lippert先生喜欢指出推理,无论什么时候它正在寻找最好的普通类型,它只会返回已经存在的类型之一 - 它不会去寻找最常见的共同祖先。“

Just because every array could be an object [] doesn't mean it should. 仅仅因为每个数组都可以是一个object []并不意味着它应该。 From a compiler perspective that'd be a trivial last-resort choice, but a very counter-intuitive one for the developer, I guess. 从编译器的角度来看,这是一个微不足道的最后选择,但对于开发人员而言,这是一个非常反直觉的选择。

To expand on Joey's answer, consider this example: 要扩展Joey的答案,请考虑以下示例:

interface IFoo { }
interface IBar { }

class A : IFoo, IBar { }
class B : IFoo, IBar { }

var array = new [] { new A(), new B() };

Both classes implement both interfaces (and also derive from object ), so which type should be inferred for array ? 这两个类都实现了两个接口(并且也从object派生),因此应该为array推断出哪种类型?


To answer your comment, consider the case where A and B share only one interface: 要回答您的评论,请考虑AB只共享一个界面的情况:

interface IFoo { }

class A : IFoo { }
class B : IFoo { }

var array = new [] { new A(), new B() };

Both A and B share object as their base class, but it'd be unhelpful and mostly useless to infer this for the array type. AB共享object作为它们的基类,但是对于数组类型推断它是没有用的并且几乎没用。 One would expect it to be IFoo if anything, so it would violate the principle of least astonishment . 如果有的话,人们会认为它是IFoo ,因此它会违反最不惊讶原则 However, this cannot be done consistently, as I've illustrated. 但是,正如我已经说明的那样,这不可能一致地完成。

The safest and most consistent behaviour here is simply not to allow type inference. 这里最安全和最一致的行为就是不允许类型推断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM