Tuesday, December 7, 2010

More Boxing

What should make you suspicious of implicit boxing, well, the Equals methods should always ring alarm bells, it's inherited from the base Object class that everything derives from and if the Value Type you are using didn't provide a replacement that takes a type of the value type then an object will be needed.
Similarly with CompareTo, not derived from Object this time, but implemented from IComparable and it takes as a parameter? Anyone? yep, Object .

Strings lure unwary coders into boxing as well, the String.Concat method offers overloads that can easily cause implicit boxing, for example:

using System;
using System.Windows.Forms;

public class Program{
  public static void Main() {

    Int32 number = 5;
    MessageBox.Show("This message Box was brought to you with the help of the number " + number);
  }
}

Using ILDasm to view the IL code:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       26 (0x1a)
  .maxstack  2
  .locals init (int32 V_0)
  IL_0000:  nop
  IL_0001:  ldc.i4.5
  IL_0002:  stloc.0
  IL_0003:  ldstr      "This message Box was brought to you with the help "
  + "of the number "
  IL_0008:  ldloc.0
  IL_0009:  box        [mscorlib]System.Int32
  IL_000e:  call       string [mscorlib]System.String::Concat(object,
                                                              object)
  IL_0013:  call       valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string)
  IL_0018:  pop
  IL_0019:  ret
} // end of method Program::Main

IL_009 shows the Int32 value type being boxed to allow it to be passed to the implicitly called String.Concat(object, object) on line IL_00e.

Boxing isn't difficult to avoid in most cases, for the above example a quick glance at MSDN will tell you that String.Concat offers a (String, String) overload, the first parameter I used was a string already, the boxing problem was caused by the Int32 and if I use the ToString  method available  on Int32 there will be no need to box. Use: MessageBox.Show("This message Box was brought to you with the help of the number " + number.ToString()); instead and the IL becomes:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       27 (0x1b)
  .maxstack  2
  .locals init (int32 V_0)
  IL_0000:  nop
  IL_0001:  ldc.i4.5
  IL_0002:  stloc.0
  IL_0003:  ldstr      "This message Box was brought to you with the help "
  + "of the number "
  IL_0008:  ldloca.s   V_0
  IL_000a:  call       instance string [mscorlib]System.Int32::ToString()
  IL_000f:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
  IL_0014:  call       valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string)
  IL_0019:  pop
  IL_001a:  ret
} // end of method Program::Main

I think for the next post I'll mumble a bit about more ways to avoid boxing.