将int 转换为object
我遇到了问题:为什么不能将int[]
为object[]
,例如object[] o = new int[] { 0, 1, 2 };
同时我可以强制转换为object
并返回int[]
。
我很高兴听到深刻的答复。
直接来自文档 :
数组协方差特别不扩展到值类型的数组。 例如,不存在允许将int []视为对象[]的转换。
整数或任何其他值类型的数组不是对象数组。 值类型与引用类型具有不同的存储特征。 一系列(引用类型)对象包含一个对象引用列表(对象本身位于堆中),因此槽总是一个恒定的宽度。 另一方面,值类型将它们的值直接存储在数组中 ,因此插槽可以是任何宽度。 这使得两者之间的转换毫无意义。
这有点让人困惑,因为即使值类型是从System.Object派生的,它们的行为与引用类型的行为也大不相同,并且只有通过编译器和运行时对它们进行神奇的处理才能实现值类型的对象行为(例如装箱)。 ,它不会扩展到数组。
作为旁注,铸造arrays是一个很好的实践。 我不会这样做。
对于要转换为类型B
的类型A
的实例,必须满足下列条件之一:
- 存在从
A
到B
的隐式 / 显式转换; - 有层次关系。 这种关系可以通过以下两种方式之一实现:
- 从
B
导出A
(例如,class A : B {}
) - 协方差/逆变。 C#允许协方差:
- 引用类型数组(
string[]
>object[]
) (*) - 接口/委托中的generics类型参数(
IEnumerable
IEnumerable
和Func
>>Func
) - 委托(
string Method() {}
可以分配给delegate object Del();
)
- 引用类型数组(
- 从
您不能将int[]
为object[]
因为上述条件均不正确。
(*) – 你应该避免这种情况 – 数组协方差被破坏了, 它被简单地添加,以便CLR支持类似Java的语言 。
虽然类型System.Int32
派生自object,并且对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和同一个对象。