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

Chu*_*ris 32 .net c# object new-operator c#-4.0

这两行之间没有区别,因为第二行中的编译器理解它是int类型的数组.

var x = new int[] { 1, 2, 3 };   //Fine, x is int[]
var x = new [] { 1, 2, 3 };      //Fine, x is int[]
Run Code Online (Sandbox Code Playgroud)

但为什么我不能用不同类型做到这一点?为什么编译器不将我的变量转换为类型对象

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"
Run Code Online (Sandbox Code Playgroud)

编辑:

谢谢你的所有答案.但我仍然想知道,使编译器无法转换为类型的所有表达式的优缺点是object什么?(因为我使用var符号,这意味着它不能是任何类型.我这样理解.)为什么编译器不通过继承树找到最近类型的数组成员?

Joe*_*oey 38

new []符号是用于保存您键入一个明确的类型数组成员(或允许您创建阵列,其中它的元素有一个匿名的类型),但它的类型推断是有限的,所有的元素都必须共享相同的类型或可隐式转换至少由一个成员共享的共同类型.参见C#规范,第7.6.10.4节:

第三种形式的数组创建表达式称为隐式类型的数组创建表达式.它与第二种形式类似,不同之处在于未明确给出数组的元素类型,而是确定为数组初始值设定项中表达式集的最佳公共类型(第7.5.2.14节).

以下是隐式类型化数组创建表达式的示例:

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
Run Code Online (Sandbox Code Playgroud)

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

这里的关键点是"最常见的类型"只能是已经存在的类型之一.正如Damien_The_Unbeliever在评论中所 指出的那样:"正如Lippert先生喜欢指出推理,无论什么时候它正在寻找最好的普通类型,它只会返回已经存在的类型之一 - 它不会去寻找最衍生共同的祖先.".

仅仅因为每个阵列都可以是一个object []并不意味着它应该.从编译器的角度来看,这是一个微不足道的最后选择,但对于开发人员而言,这是一个非常反直觉的选择.

  • 在数组中添加一个`new Object()`,它编译得很好.正如Lippert先生喜欢指出推论,无论什么时候它正在寻找最好的常见类型,它只会返回已经存在的类型之一 - 它不会寻找最衍生的共同祖先. (13认同)

Wil*_*den 18

要扩展Joey的答案,请考虑以下示例:

interface IFoo { }
interface IBar { }

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

var array = new [] { new A(), new B() };
Run Code Online (Sandbox Code Playgroud)

这两个类都实现了两个接口(也来自object),所以应该推断出哪种类型array


为了回答您的评论,考虑的情况AB分享只有一个接口:

interface IFoo { }

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

var array = new [] { new A(), new B() };
Run Code Online (Sandbox Code Playgroud)

双方AB分享object他们的基类,但它会是无益的,大多无用推断此为数组类型.IFoo如果有的话,人们会期待它,所以它会违反最不惊讶原则.但是,正如我已经说明的那样,这不可能一致地完成.

这里最安全和最一致的行为就是不允许类型推断.