Boxing nullables

March 18, 2009 at 12:36 PMAndre Loker

When value types are boxed, the boxed version has the same type as the type being boxed.

For example, boxing an int creates an object of type int:

   1: int number = 42;
   2: object boxedInt = number;
   3: Assert.IsTrue(boxedInt.GetType() == typeof(int));

Likewise for structures such as Guid:

   1: Guid id = Guid.NewGuid();
   2: object boxedGuid = id;
   3: Assert.IsTrue(boxedGuid.GetType() == typeof(Guid));

So far so good. But what happens if you box a nullable value type?

   1: int? nullableNumber = 42;
   2: object boxedNullable = nullableNumber;
   3: Assert.IsTrue(boxedNullable.GetType() == typeof(int?));

Maybe you expected this (I didn’t), but this fails. If you test boxedNullable.GetType() you will get “System.Int32”.

It seems that nullable values (which are nothing more than instances of the Nullable<T> structure) are boxed slightly different than normal value types:

  • if the nullable has no value (HasValue is false), the nullable is boxed as null
  • if the nullable has a value, that value is boxed

This way boxing is slightly more efficient because Nullable<T> contains two fields (“boolean hasValue” and “T value”) and the fact that either null or the boxed value is returned during boxing already encodes the value of hasValue. Thus, this seems to be a smart choice. And why would we want to bother in the first place?

Let’s say you have a method like this:

   1: public void DoSomething(params object[] objects) {
   2:   foreach(var item in objects) {
   3:     // do something depending on the type of item
   4:   }
   5: }

And you invoke it with the three objects that we created in the examples above:

   1: DoSomething(number, id, nullableNumber);

Then DoSomething has no chance of distinguishing between the type of the first and the third argument – both will be System.Int32 - which might lead to undesired or unexpected behaviour.

Conclusion

If your code makes decisions based on the type of a boxed value be aware that nullable values are boxed slightly different: they lose their “Nullable-ness” and become either null or the boxed version of the value that they hold.

Posted in: C#

Tags: ,

Comments (1) -

Thank you for that post. I've learned a lot on that. Thank you also for the reminder that we must aware that nullable values are boxed slightly different.

Pingbacks and trackbacks (3)+