将int []转换为object []

时间:2014-03-05 23:15:52

标签: c# clr

我遇到了问题:为什么不可能将int[]转换为object[],例如 object[] o = new int[] { 0, 1, 2 };

与此同时,我可以转换为object并返回int[]

我很高兴听到深刻的回答。

3 个答案:

答案 0 :(得分:7)

直接来自the docs

  

数组协方差特别不会扩展到值类型的数组。例如,不存在允许将int []视为对象[]的转换。

一组int或任何其他值类型一个对象数组。值类型与引用类型具有不同的存储特征。一组(引用类型)对象包含一个对象引用列表(对象本身存在于堆中),因此槽总是一个恒定的宽度。另一方面,值类型将其值直接存储在数组中,因此插槽可以是任何宽度。这使得两者之间的转换毫无意义。

这有点令人困惑,因为即使值类型是从System.Object派生的,它们的行为与引用类型的行为也大不相同,并且值类型的对象行为(例如装箱)只能通过对它们进行神奇的处理才能实现。编译器和运行时,它不会扩展到数组。

作为旁注,铸造阵列是一个很好的实践。我不会这样做。

答案 1 :(得分:1)

对于类型A可投射类型B的实例,必须满足下列条件之一:

  1. AB的转换为implicit / explicit;
  2. 存在层次关系。这种关系可以通过以下两种方式之一实现:
    1. A(例如B
    2. 派生class A : B {}
    3. 协方差/逆变。 C#允许协方差:
      1. 参考类型数组(string[]> object[](*)
      2. 接口/代理中的泛型类型参数(IEnumerable<string>&gt; IEnumerable<object>Func<string>&gt; Func<object>
      3. 代表(string Method() {}可以分配到delegate object Del();
  3. 您无法将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}}是同一个对象。