Sep 17

In the previous posts, I’ve presented the basics on boxing and unboxing. Today, we’ll take a deep dive into several scenarios which illustrate how boxing/unboxing can occur without you even noticing it. Lets start with a quick recap. Suppose we’ve got the same structure as used in the previous examples:

public struct Student {
    public String Name { get; set; }
    public Int32 Age { get; set; }

As we’ve seen, you’ll get a boxing operation whenever you pass an instance of Student to an element which expects a reference type. In other words, the next instructions result in a boxing operation:

Student std = new Student {Name = "Luis", Age = 34};
Object boxedStd = std; //boxing here!

The previous snippet shows an explicit boxing operation. You might need to do this to improve performance. For instance, suppose you need to perform several calls and that all of them expect reference types. Here’s a naive way of doing that:

//all callx methods expect a reference to an Object instance
Call1( std );
Call2( std );
Call3( std );

If you do this, you’ll end up performing three boxing operations (one for each method invocation) because Call1,Call2 and Call3 are expecting to receive a reference type. In these cases,you should probably perform a manual boxing operation before calling those methods:

//all callx methods expect a reference to an Object instance
Object boxedStd = std; //1 boxing operation
Call1( boxedStd );
Call2( boxedStd );
Call3( boxedStd );

With the previous change, we’ve managed to perform a single boxing operation (instead of three). It’s a small improvement, but one that might make a difference when you have lots of calls. Besides method calls, there are other scenarios where you’ll end up with boxing.

If you look at the ValueType type definition, you’ll notice that it inherits from the Object type. So, what happens when you call one of the methods defined by the base class? The answer is: it depends. If you override one of the inherited virtual methods, then the CLR won’t box the instance and you’ll get a non-virtual method call (the CLR can do this since value types are implicitly sealed). *However*, if your override calls the base method, then the value type instance will get boxed because the base method’s this parameter expects a reference type.

When you’re calling a non-virtual method (or a non-overridden method), you’ll get boxing for the same reasons presented in the previous paragraph. There’s still one last scenario where you need to consider boxing. As you know, a struct might implement one or more interfaces. Casting an unboxed instance of a value type to one of the interfaces it implements requires boxing. Take a look at the next example:

public interface IStudent {
    String Name { get; set; }
public struct Student: IStudent {
    public String Name { get; set; }
    public Int32 Age { get; set; }

And here’s some code which explains where boxing will occur:

Student std = new Student {Name = "Luis", Age = 34};
String nameFromStruct = std.Name;//no boxing here
IStudent stdRef = std;//boxing
String nameFromInterface = stdRef.Name; //gets value from boxed ref

As an extra bonus, do you think you’ll get boxing in the next call? If so, why is that? And if there is boxing, can you do anything to prevent it from happening?

var toString = std.ToString( );

And I think we’ve covered most boxing related scenarios. Stay tuned for more…

3 comments so far

  1. Thisissparta
    7:33 am - 9-19-2010


    In last code snippet you won”t get boxing because ToString() override in ValueType and, i think, doesn”t call base method.

    P.S.: thank for you great series – Repetition is The Mother of Learning.

  2. luisabreu
    9:53 am - 9-20-2010

    well, you *will* get boxing because you”re calling a virtual method. the optimization I”ve mentioned will only occur when the value type you”re creating *overrides* the ToString method and you don”t call the base member. So, the solution would be to override the ToString method and make sure that you don”t call the base method.

  3. Thisissparta
    11:50 am - 9-20-2010

    Indeed. I”m so inattentive 🙂