There are cases when an instance of a value type needs to be treated as an instance of a reference type. For situations like this, a value
Below is some examples of boxing/unboxing
ArrayList ints = new ArrayList();
myInts.Add(1); // boxing
myInts.Add(2); // boxing
int myInt = (int)ints [0]; // unboxing
Console.Write("Value is {0}", myInt); // boxing
The code
int x = 42;
Console.Writeline("The value of x is {0}", x );
actually boxes and unboxes because Writeline
does an int
cast inside. To avoid this you could do
int x = 42;
Console.Writeline("The value of x is {0}", x.ToString());
Beware of subtle bugs!
You can declare your own value types by declaring your own type as struct
. Imagine you declare a struct
with lots of properties and then put some instances inside an ArrayList
. This boxes them of course. Now reference one through the []
operator, casting it to the type and set a property. You just set a property on a copy. The one in the ArrayList
is still unmodified.
For this reason, value types must always be immutable, i.e. make all member variables readonly
so that they can only be set in the constructor and do not have any mutable types as members.
There is almost never a good reason to deliberately box a value type. Almost always, the reason to box a value type is to store it in some collection that is not type aware. The old ArrayList, for example, is a collection of objects, which are reference types. The only way to collect, say, integers, is to box them as objects and pass them to ArrayList.
Nowadays, we have generic collections, so this is less of an issue.
I think a good example of boxing in c# occurs in the non-generic collections like ArrayList.
In general, you typically will want to avoid boxing your value types.
However, there are rare occurances where this is useful. If you need to target the 1.1 framework, for example, you will not have access to the generic collections. Any use of the collections in .NET 1.1 would require treating your value type as a System.Object, which causes boxing/unboxing.
There are still cases for this to be useful in .NET 2.0+. Any time you want to take advantage of the fact that all types, including value types, can be treated as an object directly, you may need to use boxing/unboxing. This can be handy at times, since it allows you to save any type in a collection (by using object instead of T in a generic collection), but in general, it is better to avoid this, as you're losing type safety. The one case where boxing frequently occurs, though, is when you're using Reflection - many of the calls in reflection will require boxing/unboxing when working with value types, since the type is not known in advance.
I would recommend you 2 nice articles of Eric Lippert
http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx
http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx
Here is the quote that I would 100% agree with
Using the stack for locals of value type is just an optimization that the CLR performs on your behalf. The relevant feature of value types is that they have the semantics of being copied by value, not that sometimes their deallocation can be optimized by the runtime.
In 99% applications developers should not care about why Value types are in stack and not in the heap and what performance gain could we have here. Juts have in mind very simple rules:
Any rules allows exclusions in special cases, but do not try to over-optimize.
p.s. I met some ASP.NET developers with 2-3 years experience who doesn't know the difference between stack and heap. :-( I would not hire such a person if I'm an interviewer, but not because boxing/unboxing could be a bottleneck in any of ASP.NET sites I've ever seen.