对于元素为引用类型的数组,CLR允许将数组元素从一种类型转型另一种。
成功转型要求数组维数相同,而且必须从元素源类型到目标类型的隐式或显示转换。
CLR不允许将值类型元素的数组转型为其他任何类型。(不过,可用Array.Copy方法创建新数组并在其中填充元素来模拟这种效果。)
Array.Copy的作用不仅仅是将元素从一个数组复制到另一个。
Copy方法还能正确处理内存的重叠区域。
Copy方法还能再复制每个数组元素时进行必要的类型转换:
1.将值类型的元素装箱为引用类型的元素。比如将一个int[]复制到一个object[]中。
2.将引用类型的元素拆箱为值类型的元素。比如将一个object[]复制到一个int[]中。
3.加宽CLR基元值类型。比如将一个int[]的元素复制到一个Double[]中。
4.在两个数组之间复制时,如果进从数组类型证明不了两者的兼容性,比如从object[]转型为IFormattable[],就根据需要对元素进行向下类型转换。如果object[]中的每个对象都实现了IFormattable,Copy方法就能成功执行。
//--
//--
FCL频繁运用了Array的Copy方法。
有时确实需要将数组从一种类型转换为另一种类型。这种功能称为数组协变性(array covariance)。但在利用它时要清楚由此而来的性能损失。
上述代码中,obj1dim变量被定义为object[]类型,但实际引用的是一个string[]。编译器允许代码将5放到数组元素中,因为5是Int,而int派生自object。虽然编译能通过,但CLR必须保证类型安全。对数组元素赋值时,它必须保证赋值的合法性。所以,CLR必须在运行时检查数组包含的是不是int元素。
//--
注意
如果只是需要将数组的某些元素赋值到另一个数组,可选择System.Buffer的BlockCopy方法,它比Array的Copy方法快。但Buffer的BlockCopy方法只支持基元类型,不提供像Array的Copy方法那样的转型能力。设计BlockCopy的目的实际是将按位兼容(bitwise-compatible)的数据从一个数组类型复制到另一个按位兼容的数据类型,比如将包含Unicode字符的一个Byte[](按字节的正确顺序)复制到一个Char[]中。该方法一定程度上弥补了不能将数组当作任意类型的内存块来处理的不足。
要将一个数组的元素可靠地复制到另一个数组,应该使用System.Array的ConstrainedCopy方法。该方法要么完成复制,要么抛出异常,总之不会破坏目标数组中的数据。这就允许ConstrainedCopy在约束执行区域(Constrained Excecution region,CER)中执行。为了提供这种保证,ConstrainedCopy要求源数组的元素类型要么与目标数组的元素类型相同,要么派生自目标数组的元素类型。另外,它不执行任何装箱、拆箱或向下类型转换。