views:

1020

answers:

9

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 type instance can be converted into a reference type instance through a process called boxing. When a value type instance is boxed, storage is allocated on the heap and the instance's value is copied into that space. A reference to this storage is placed on the stack. The boxed value is an object, a reference type that contains the contents of the value type instance.

Understanding .NET's Common Type System

In Wikipedia there is an example for Java. But in C#, what are some cases where one would have to box a value type? Or would a better/similar question be, why would one want to store a value type on the heap (boxed) rather than on the stack?

+11  A: 

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.

Randolpho
Reflection still forces you to box/unbox values, and is very valuable...
Reed Copsey
Very true. However, reflection is something you want to limit to "I absolutely cannot do this any other way" cases, so I think my first sentence stands well.
Randolpho
+2  A: 

I think a good example of boxing in c# occurs in the non-generic collections like ArrayList.

bruno conde
+5  A: 

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.

Reed Copsey
+1  A: 

One example would when a method takes an object parameter and a value type must be passed in.

Kevin
+1  A: 

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
BengtBe
Example != Use Case
Philip Wallace
+1  A: 

One of the situations when this happens is for example if you have method that expect parameter of type object and you are passing in one of the primitive types, int for example. Or if you define parameter as 'ref' of type int.

epitka
-1. There is no boxing in C# when you pass by reference. See the note here: http://msdn.microsoft.com/en-us/library/14akc2c7.aspx
Randolpho
+1 from me. Every day something new to learn.
epitka
+3  A: 

Boxing generally happens automatically in .NET when they have to; often when you pass a value type to something that expects a reference type. A common example is string.Format(). When you pass primitive value types to this method, they are boxed as part of the call. So:

int x = 10;
string s = string.Format( "The value of x is {0}", x ); // x is boxed here

This illustrates a simple scenario where a value type (x) is automatically boxed to be passed to a method that expects an object. Generally, you want to avoid boxing value types when possible ... but in some cases it's very useful.

On an interesting aside, when you use generics in .NET, value types are not boxed when used as parameters or members of the type. Which makes generics more efficient than older C# code (such as ArrayList) that treat everything as {object} to be type agnostic. This adds one more reason to use generic collections, like List<T> or Dictionary<T,K> over ArrayList or Hashtable.

LBushkin
+2  A: 

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:

  1. Avoid boxing/unboxing when not necessary, use generics collections. Most problems occurs not when you define your own types, but when you use existing types inproperly (defined by Microsoft or your collegues)
  2. Make your value types simple. If you need to have a struct with 10-20 fields, I suppose you'ld better create a class. Imagine, all that fields will be copied each time when you occasionally pass it a function by value...
  3. I don't think it is very useful to have value types with reference type fields inside. Like struct with String and object fields.
  4. Define what type you need depending on required functionality, not on where it should be stored. Structs have limited functionality comparing to classes, so if struct cannot provide the required functionality, like default constructor, define class.
  5. If something can perform any actions with the data of other types, it is usually defined as a class. For structs operations with different types should be defined only if you can cast one type to another. Say you can add int to double because you can cast int to double.
  6. If something should be stateless, it is a class.
  7. When you are hesitating, use reference types. :-)

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 and interviewer, but not because boxing/unboxing could be a bottleneck in any of ASP.NET sites I've ever seen.

Bogdan_Ch
Good answer. +1 I agree; if developers don't know the difference between the stack and the heap, it highlights a real lack of understanding of the basic principles of how their data is being stored and pointed to. This could lead them to introduce serious bugs (assuming that changing an object in one collection doesn't change it in another, e.g.).
StriplingWarrior
Thanks for the linked articles!
felideon
A: 

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.

Hans Malherbe
This is what one could call "micro optimization" and I would recommend to avoid the manner of coding like one that is shown in the second code block. In fact here instead of boxing you create a new string and then this string is copied, because strings are immutable and when you pass it as ByVal paremeter, it should be copied. So, do you really think that this code will be more optimal ? I doubt so. If Ms created a basic function Console.Writeline(string format, int i); that accepts an integer parameter, you should use it.
Bogdan_Ch
It's not an optimization at all, it just illustrates the principle. What do you mean by "it should be copied"?
Hans Malherbe