LA.NET [EN]

Sep 16

As we’ve seen, value types have better performance than reference types because they’re allocated in the stack, they’re not garbage collected nor do they get the extra weight generally associated with reference types. There are, however, some times where we need a “reference to  a value object” (yes, I wanted to write “reference to a value object”). In the old days, that would happen whenever you needed a collection of value objects (as you recall, in .NET 1.0/.NET 1.1 there were no generics). Here’s a small example:

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

Now, and this is important, pay attention to the following snippet:

var cll = new ArrayList();
var std = new Student {Name = "Luis", Age = 10};
cll.Add(std);
var std2 = (Student)cll[0];
std2.Name = "Abreu";

If you look at the docs, you’ll notice  that the Add method expects an Object instance. In other words,it requires a reference type and not a value type. If you go ahead and compile the previous snippet,you won’t get any compilation errors. What’s going on here? What you’re seeing is perfectly normal and it’s called boxing. Boxing allows us to convert a value type into a reference type. Boxing involves a rather simple algorithm:

  1. allocate memory on the managed heap for the value object plus the “traditional” overhead space required for all the reference types (btw, I’m talking about the type object pointer and the sync block index).
  2. copy the values of the value type’s fields into the heap’s allocated memory.
  3. use the returned memory address as the “converted” reference type instance.

When the compiler detected that the Add method requires a reference type, it went ahead and applied the previous algorithm in order to transform the value type and pass a reference into the method. In other words, what got added to the cll collection was the reference obtained from step 3 (and not the std variable).

This has lots of implications which might not be obvious at first. For instance, if you think that the following snippet should print true, you’re wrong:

Console.WriteLine(std.Name == std2.Name);

Before getting into why that happens, we need to understand unboxing. Since it’s 22:37 and I still haven’t had my dinner, I’ll leave the unboxing post for later :)

Stay tuned for more!

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>