我遇到了问题:为什么不可能将int[]
转换为object[]
,例如
object[] o = new int[] { 0, 1, 2 };
与此同时,我可以转换为object
并返回int[]
。
我很高兴听到深刻的回答。
答案 0 :(得分:7)
直接来自the docs:
数组协方差特别不会扩展到值类型的数组。例如,不存在允许将int []视为对象[]的转换。
一组int或任何其他值类型不一个对象数组。值类型与引用类型具有不同的存储特征。一组(引用类型)对象包含一个对象引用列表(对象本身存在于堆中),因此槽总是一个恒定的宽度。另一方面,值类型将其值直接存储在数组中,因此插槽可以是任何宽度。这使得两者之间的转换毫无意义。
这有点令人困惑,因为即使值类型是从System.Object派生的,它们的行为与引用类型的行为也大不相同,并且值类型的对象行为(例如装箱)只能通过对它们进行神奇的处理才能实现。编译器和运行时,它不会扩展到数组。
作为旁注,铸造阵列是一个很好的实践。我不会这样做。
答案 1 :(得分:1)
对于类型A
的可投射类型B
的实例,必须满足下列条件之一:
A
到B
的转换为implicit / explicit; A
(例如B
)class A : B {}
string[]
> object[]
)(*) IEnumerable<string>
&gt; IEnumerable<object>
和Func<string>
&gt; Func<object>
)string Method() {}
可以分配到delegate object Del();
)您无法将int[]
强制转换为object[]
,因为以上条件都不属实。
(*) - 你应该避免这种情况 - 数组协方差被破坏并且是it was added simply so that the CLR would support Java-like languages。
答案 2 :(得分:0)
虽然类型System.Int32
派生自对象,并且对System.Int32
对象实例的引用可用作System.Object
的引用,但类型为System.Int32[]
的数组不包含实例System.Int32
,也没有引用它们。相反,数组的每个元素将只保存与Int32
关联的32位数值,而不保留与对象实例关联的任何其他信息。虽然C#允许代码如下:
Object[] array = new Object[3];
int five = 5;
array[0] = five;
array[1] = five;
array[2] = array[0];
代码不会将five
或对它的引用存储到数组中。相反,对array[0]
的赋值将创建一个类型为System.Int32
的新对象,该对象保存数字5并存储对该引用的引用。然后,对array[1]
的分配将创建另一个类型为System.Int32
的新对象,该对象也保存值5,并存储对该对象的引用。第三个作业将array[2]
存储为与array[0]
相同的对象。请注意,即使所有三个阵列插槽似乎都保持数字5,它们实际上仍然拥有更多信息。该数组还假设array[0]
和array[2]
保持对一个对象的引用,而array[1]
保存对另一个对象的引用。
将引用类型强制转换为其父类型时,需要生成的引用以标识与原始类型相同的对象。因此,由结果引用标识的对象不能封装除原始标识的对象之外的任何其他信息(毕竟它是相同的对象!)。由于Object[]
,即使其元素都标识System.Int32
的实例,也会将信息封装在int[]
以外的信息之外,因此int[]
和Object[]
不可能{{1}}是同一个对象。