1. What kind of arrays is possible to cast.
2. How can the Array.Copy() method helps with array conversion and casting.
3. The array covariance is conversion an array from one type to another type.
4. The Array.ConstrainedCopy and the Buffer.BlockCopy are methods which allow us to perform copy faster.
The CLR allows implicit and explicit casting arrays only with reference type elements. To allow casting the arrays must have:
1. The same number of dimensions.
2. Conversion from the source element type to the target element type must exist.
The CLR doesn’t allow casting of value type elements, but to get desired effect for value type elements we can use the Array.Copy method.
Examples:
StreamWriter[] sourceArray = new StreamWriter[5];
//We get compile time error ‘Cannot convert type ‘System.IO.StreamWriter[]’ //to ‘object[*,*]”
//Casting arrays must have the same number of dimensions
Object[,] targetArray = (Object[,])sourceArray;
//We get compile time error ‘Cannot convert type ‘System.IO.StreamWriter[]’ to ‘string[]’
//Conversion from source type element to target type element must exist
string[] targetArray = (string[])sourceArray;
//We get Common Language Runtime error ‘System.InvalidCastException
//2. Conversion from source type element to target type element must exist
string[] stringTargetArray = (string[])objectSourceArray;
int[] intSourceArray = new int[5];
//We get compile time error "Cannot convert type ‘int[]’ to ‘object[]’"
//CLR allows casting only arrays with reference type elements
object[] targetArray = (object[])intSourceArray;
//Casting has been succesfully completed
StreamWriter[] sourceArray = new StreamWriter[5];
Object[] targetArray = (Object[])sourceArray;
The Array.Copy() method can perform:
1. Boxing
int[] intSourceArray = new int[5];
object[] targetArray = new object[intSourceArray.Length];
Array.Copy(intSourceArray, targetArray, intSourceArray.Length);
2. Unboxing
object[]sourceArray= new object[5] {0, 1, 2, 3, 4};
int[] targetArray = new int[sourceArray.Length];
Array.Copy(sourceArray, targetArray, sourceArray.Length);
Of course if reference type array isn’t initialized we will get System.InvalidCastException
("At least one element in the source array could not be cast down to the destination array type.")
3. Widening
int[] sourceArray = new int[5];
double[] targetArray = new double[sourceArray.Length];
Array.Copy(sourceArray, targetArray, sourceArray.Length);
4. Casting between arrays which ability to cast can’t be determined.
public struct MyValueType : IComparable
{
public int CompareTo(object obj)
{
return 0;
}
}
MyValueType []sourceArray = new MyValueType[5];
IComparable []targetArray = new IComparable[sourceArray.Length];
Array.Copy(sourceArray, targetArray, sourceArray.Length);
If we use explicit casting we we’ll get complie time error
//Cannot convert type ‘Arrays.Program.MyValueType[]’ to ‘System.IComparable[]’
IComparable[] targetArray = (IComparable[])sourceArray;
In some situations it is usefull to cast an array from one type to another. This kind of functionality is called array covariance. When we use array covariance we should always remember about performance hit, because CLR must ensure type safety.
Example:
String[] sourceArray = new String[5];
Object[] targetArray = (Object[])sourceArray;
//Correct, but performance hit. CLR must ensure type safety.
targetArray[0] = "Hello World";
//ArrayTypeMismatchException
//Attempted to access an element as a type incompatible with the array.
targetArray[1] = 1;
To make a copy faster we can use the Array.ConstrainedCopy method, which doesn’t have advantages of the Array.Copy method such as Boxing, Unboxing, Widening, casting arrays which casting abilities can’t be determined, but it makes the ConstrainedCopy method faster and it throws exception if data can be damaged.
Also exist the Buffer.BlockCopy method which make bitwise copy, but support only primitive types and in case of data corruption doesn’t throw exception.