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

发布于 2024-12-27 07:17:56 字数 620 浏览 0 评论 0原文

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

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

但为什么我不能对不同类型执行此操作?为什么编译器不将我的变量转换为 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"

编辑:

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

There is no difference between these two lines, because the compiler, in the second line, understands that it is an array of type 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? (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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

书信已泛黄 2025-01-03 07:17:56

new [] 表示法用于节省您键入数组成员的显式类型(或允许您创建其元素具有匿名类型的数组),但其类型推断受到限制,因为所有元素必须共享相同的类型,或者可以隐式转换为至少一个成员共享的公共类型。请参阅 C# 规范,第 7.6.10.4 节:

第三种形式的数组创建表达式称为隐式类型数组创建表达式。它与第二种形式类似,只是没有显式给出数组的元素类型,而是将其确定为数组初始值设定项中表达式集的最佳公共类型(第 7.5.2.14 节)。

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

var a = new[] { 1, 10, 100, 1000 }; // 整数[]
var b = new[] { 1, 1.5, 2, 2.5 }; // 双倍的[]
var c = new[,] { { "你好", null }, { "世界", "!" } }; // 细绳[,]
var d = new[] { 1, "一", 2, "二" }; // 错误

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

这里的关键点是“最佳常见类型”只能是已经存在的类型之一。正如Damien_The_Unknowner在评论中指出的那样:“正如Lippert先生喜欢指出的那样推论,每当它寻找最佳公共类型时,它只会返回已经存在的类型之一 - 它不会去寻找最衍生的公共祖先。”

仅仅因为每个数组都可以是一个 object [] 并不意味着它应该是。从编译器的角度来看,这将是一个微不足道的最后选择,但我想对于开发人员来说这是一个非常违反直觉的选择。

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. See C# Specification, section 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.

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. An explicitly typed array creation expression must be used in this case, for example specifying the type to be 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.”.

Just because every array could be an object [] doesn't mean it should. From a compiler perspective that'd be a trivial last-resort choice, but a very counter-intuitive one for the developer, I guess.

折戟 2025-01-03 07:17:56

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

interface IFoo { }
interface IBar { }

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

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

两个类都实现了两个接口(并且还从 object 派生),因此应该为 array 推断哪种类型?


要回答您的评论,请考虑 AB 仅共享一个接口的情况:

interface IFoo { }

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

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

AB 共享object 作为它们的基类,但是对于数组类型推断这一点是没有帮助的,而且几乎没有用处。如果有的话,人们会期望它是 IFoo ,因此它会违反原则最少的惊讶。然而,正如我所说明的,这不能始终如一地完成。

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

To expand on Joey's answer, consider this example:

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?


To answer your comment, consider the case where A and B share only one interface:

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. One would expect it to be IFoo if anything, so it would violate the principle of least astonishment. However, this cannot be done consistently, as I've illustrated.

The safest and most consistent behaviour here is simply not to allow type inference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文