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.