Casting arrays

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.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s