Boxing and Unboxing in .Net

In this article I will try to explain the concepts of Boxing and Unboxing. There are two types of objects within the .Net framework, value types and reference types. Value types are stored on the stack while reference types are always stored on the heap. Converting a value type into a reference type is called Boxing while converting it back from a reference type to a value type is called Unboxing.

Value Types

Value types are primitive types like System.Int32 (Integer in VB, int in C#) or System.Double. These types are mapped directly to the Framework Class Library (FCL) and are all derived from System.ValueType. Apart from the regular primitive types (integer, long, single, double, char, and so on) Enumerations and Structures also inherits from System.ValueTypes so they are also stored on the stack.

Reference Types

All classes are reference types and they are stored on the heap. So when you create a new instance of a class using the new keyword, memory are allocated on the heap for the object and the memory address is returned. Strings are a special case since they are also reference types, even though they are often treated as if they where value types, but that’s not the case. The difference is that you don’t have to create an instance of a string in the same manner as you would with another class.

Reference types are also Nullable, meaning that you can set the reference to Null (Nothing in VB).

Widening and Narrowing conversions

Before we go into the Boxing and Unboxing I would like to take a moment to explain the difference between a widening and a narrowing conversion. A widening conversion is always safe since there is never any risk of any data loss. For example converting an Integer into a Long (System.Int64) is a widening conversion. There is no integer value that doesn’t fit into a Long so you can always do that. However doing the opposite, converting a Long into an Integer is more risky since there are a chance that you will lose some data, since a Long can contain a number that is too high (or too low) to fit into an integer.

You can always use an implicit conversion when you do a widening conversion.

Dim i As Integer = 3
Dim l As Long
l = i 'Implicit conversion

However to do the opposite, a narrowing conversion, you need to do an explicit conversion.

i = CType(l, Integer) 'Explicit conversion
'or
i = CInt(l) 'Explicit conversion

If you don’t do an explicit conversion when you’re doing a narrowing conversion you will get a compilation error so your project will not compile (Note, VB can allow you to do an implicit conversion if you have Option Strict set to Off, something I strongly advice you not to have, C# however will never allow it). If the Long value does not fit into the Integer you will however still get a runtime error since the system will then throw a System.OverflowExeption. So when you do a narrowing conversion you must be sure that it can be done.

Doing Boxing/Unboxing

As mentioned earlier Boxing refers to the conversion of a value type to a reference type.

Dim i As Integer = 3
Dim o As Object
o = i 'Boxing the Integer into an object (reference type)

Above I do an implicit conversion of an integer to an object. This is possible since it’s a widening conversion so there is no risk of any data loss. However doing the opposite, converting the object to an integer is a narrowing conversion, where there is a risk that data will be lost.

i = o 'Implicitly doing a narrowing conversion (not allowed)
i = CInt(o) 'Explicitly doing a narrowing conversion (allowed)

In C# if you have boxed a particular type you must unbox it to the same type. You can not box an integer to an object and then unbox it to a long.

int i = 3;
long l;
object o;
o = i;
l = (long)o; //will throw a System.InvalidCastException

For the above to work, you must first unbox it to an integer and then cast it to a long.

int i = 3;
long l;
object o;
o = i;
l = (long)(int)o;

However the VB’s type conversion functions (CType and the more specific CInt, CLng, CDbl and so on) does allow this.

Dim i As Integer = 3
Dim l As Long
Dim o As Object
o = i
l = CLng(o) 'allowed

End words

I hope that you by now have a better understanding of Boxing and Unboxing. So let me end this article by saying that you should avoid doing this if possible. Doing type conversion is time consuming, and that is especially true when it comes to Boxing and Unboxing since data have to be transferred back and forth between the stack and the heap. Using Generics, which has existed in .Net since version 2.0, is a much better approach than having to deal with value type to reference type conversion.

I will cover Generics in a later article.

Have fun.

7 thoughts on “Boxing and Unboxing in .Net”

  1. Superb explanation Thanks….

    But I have 1 Question that, As per this artical Is there any possibility to data loss in C# ?

    Plz Reply…thanks in advanced.

  2. @Raj: There is always a risk of losing some data when you convert from one type into another. Converting the floating point value 3.14 in an integer is not possible so converting it to an int would result in the value 3 which means you’ve lost part of the data.

  3. Thanks.. for reply

    but as per above you mention that in C#

    In C# if you have boxed a particular type you must unbox it to the same type. You can not box an integer to an object and then unbox it to a long.

    int i = 3;
    long l;
    object o;
    o = i;
    l = (long)o; //will throw a System.InvalidCastException

    means in C# when we do boxing and unboxing it must be vise versa that is
    int -> object -> int
    long -> object -> long
    if we do int -> object -> long then it shows exception (System.InvalidCastException)

    So my Question is As per the above mention Theory IS THERE IS ANY CHANCE FOR DATA LOSS IN C# WITH BOXING AND UNBOXING ?

  4. You will not lose lose any data by doing the boxing and unboxing process by itself. However boxing is a widening operation and un unboxing is a narrowing operation. This means that when you have your value boxed you could manipulate the data and by doing so convert it to something else but the C# compiler will not allow you to do so without implicit casting which means that you can not do this without being aware of it.

  5. It’s neither of these things… It’s just wrong! Or rather as I read it I understand how it’s perceived that way since I wrote it in a very strange way. What I mean is that since C# doesn’t allow you to unbox one type to another you will not lose information during the unboxing phase. You can only lose data when you use implicit casting of one type to another, that however is not allowed during unboxing in C#. I’m sorry for the confusion.

  6. To add to my previous comment: If you use the dynamic keyword in C# a value type can directly be unboxed to another type but not without implicit casting.

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>