C# - 编译器错误 - 将 int[] 分配给 object[] 时
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
object[] obj = new object[3];
obj[0] = new object();
obj[1] = "some string";
obj[2] = 10;
string[] strings = new string[] { "one", "two", "three" };
obj = strings; //---> No Error here, Why ?
int[] ints = new int[] { 1, 2, 3 };
obj = ints; /*-> Compiler error - Cannot implicitly convert type 'int[]' to 'object[]', Why ?*/
}
}
}
在执行如上所示的步骤时,我收到编译器错误。但是,在前面的步骤中,没有错误。有人可以向我解释这种行为吗?我用的是VS 2010。
编辑 - 为了完整性,再次,这不会编译 - .NET 4.0 中的方差支持现已清理。可以将新关键字 in 和 out 与泛型类型参数结合使用。
List<object> objectList = new List<object>();
List<string> stringList = new List<string>();
objectList = stringList;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
object[] obj = new object[3];
obj[0] = new object();
obj[1] = "some string";
obj[2] = 10;
string[] strings = new string[] { "one", "two", "three" };
obj = strings; //---> No Error here, Why ?
int[] ints = new int[] { 1, 2, 3 };
obj = ints; /*-> Compiler error - Cannot implicitly convert type 'int[]' to 'object[]', Why ?*/
}
}
}
I get a compiler error while doing the step as shown above. But, in the preceding step, there is no error. Can somebody explain me this behavior ? I am using VS 2010.
EDIT - For sake of completeness, again, this won't compile - Variance support in .NET 4.0 has been cleaned up now. One can use new keywords in and out with generic type parameters.
List<object> objectList = new List<object>();
List<string> stringList = new List<string>();
objectList = stringList;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
只有引用类型的数组(例如
String
)才可以分配给其他引用类型的数组(例如Object
)。由于int
是值类型,因此它的数组不能分配给其他类型的数组。更具体地说,这称为数组协方差。仅当数组中存储的位模式与目标类型兼容时,它才有效。例如,
String[]
中的位都是对字符串的引用,并且可以安全地复制到存储对对象的引用的内存位置。然而,值类型数组存储元素的实际数据(而不只是对它们的引用)。这意味着int[]
将实际的 32 位整数存储在数组的元素中。由于无法将 32 位整数安全地复制到存储对对象或任何其他类型的引用的内存位置,因此您不能将它们的数组分配给任何其他类型的数组。请注意,从技术上讲,
int
的位可以安全地复制到存储uint
的内存位置(反之亦然)。这意味着您应该能够执行类似int[] x = new uint[10]
的操作。这实际上并不是协方差,C# 也不允许这样做。但是,它在 CLR 中是合法的,如果您愿意,您可以说服 C# 让您这样做。Only arrays of reference types (like
String
) may be assignable to arrays of other reference types (likeObject
). Sinceint
is a value type, arrays of it may not be assigned to arrays of other types.To be more specific, this is called array covariance. It only works when the bit patterns stored in the array are compatible with the destination type. For example, the bits in a
String[]
are all references to strings and can be safely copied into memory locations storing references to objects. An array of value types, however, stores the actual data of the elements (as opposed to just references to them). This means that anint[]
stores the actual 32-bit integers in the elements of the array. Since a 32-bit integer cannot be safely copied into a memory location storing a reference to an object or any other type, you cannot assign an array of them to an array of any other type.Note that technically the bits of an
int
can be safely copied into a memory location storing auint
(and vice-versa). This means that you should be able to do something likeint[] x = new uint[10]
. This is not actually covariance and C# does not allow it. However, it is legal in the CLR and you can convince C# to let you do it if you want to.string
和object
都是引用类型。也就是说,这些类型的变量实际上存储了指向内存中其他位置的指针。int
是一种值类型。也就是说,数据直接存储在声明变量的地方。这意味着引用类型数组与值类型数组根本不同。引用类型数组存储为指针数组。因为指针的大小都相同,这意味着将
string[]
重新解释为object[]
简单地意味着调整访问中的项目时完成的类型检查数组(粗略地说)。然而,在
int[]
中,值直接存储在数组中; int 值连接在一起。不涉及任何指针。这意味着要将int[]
重新解释为object[]
需要将数组中存储的每个值装箱到一个对象中。因此,为什么您不能使用简单的强制转换或赋值来完成此操作 - 创建新数组的操作时间复杂度为 O(n)。相反,您可以使用 Array.Copy 来为您处理所有装箱操作。string
andobject
are both reference types. That is, a variable of those types actually stores a pointer to somewhere else in memory.int
is a value type. That is, the data is stored directly where the variable is declared.This means that an array of reference types is fundamentally different to an array of value types. An array of reference types is stored as an array of pointers. Because pointers are all the same size, this means that to re-interpret a
string[]
as anobject[]
simpy means adjusting the type checking done when accessing the items in the array (roughly speaking).However, in an
int[]
, the values are stored in the array directly; the int values are concatenated together. No pointers are involved. This means that to re-interpret anint[]
as anobject[]
requires boxing every value stored in the array into an object. Hence why you can't do it using a simple cast or assignment - it's an O(n) operation that creates a new array. Instead, you can useArray.Copy
which deals with all the boxing for you.为什么这不起作用在这里的许多答案中都有说明,所以我不会尝试复制粘贴他们所说的内容。
如果您或其他人出于某种原因确实想要这样做(将
int[]
转换为object[]
),您可以像这样使用 LINQ:;)
Why that is not working is stated in many answers here, so I will not try to copy-paste what they said.
If you, or someone else really want to do that (convert
int[]
toobject[]
) for some reason, you can use LINQ like so:;)
我看到的是一个引用类型数组可以分配给另一个引用类型数组,而值类型数组则不能。对我来说有意义
what I see is an array of reference types can be assigned of another array of reference types while an array of value types cannot. Make sense to me
如果您安装了 Visual Studio,您会在 VC# 下的某个位置找到 C# 语言规范的 doc 文件。第 12.5 章涉及协方差,其中提到
这可能无法回答您的问题,但这样做是规范中经过深思熟虑的决定。
If you have a Visual Studio installation you will find the C# Language Speicifcation as doc file somewhere under VC# . Chapter 12.5 deals with covariance and there it says
This may not answer your question, but it was a deliberate decision in the spec to do it that way.