Wednesday, October 1, 2008

Boxing and arrays

There is one more catch with boxing (see also my former post Boxing and explicit conversions). Consider the code

public struct X
{
   public string Value { get; set; }
}

public void Fun()
{
   X x1 = new X { Value="original string 1" };
   X x2 = new X { Value="original string 2" };
   X[] array = new X[] { x1, x2 };

   array[0].Value = "modified string";
   //! x1 is not changed
}


I am occasionally amazed that x1 has "original string 1" on the line marked '!' although array[0] reads "modified string". Hell yes, that is because of boxing again. If X was classx1 would be changed, too.

Boxing and explicit conversions

Imagine you are writing a method that will process a number. You need to accept object as an argument.*) You know that you will accept integers. You have considered the usage of int and long, and you have chosen long since int can be safely converted to long. So you prepare something like

void ProcessNumber(object o)
{
   long number = (long)o; //!
   //do something with number
}


You test your method, and — surprise — you receive System.InvalidCastException on the line marked '!' when calling ProcessNumber(1). The problem is that boxing is involved, and the argument is not longer just int.

You can cast a boxed value only if it is of the very same type!

If it is not certain that you will receive single type in all calls, you had better use the appropriate method of the System.Convert class.

*) Consider accessing of properties via reflection.