Even though with the .NET framework we don't have to actively worry about memory management and garbage collection (GC), we still have to keep memory management and GC in mind in order to optimize the performance of our applications. One of the things we need to be aware of is how the Common Language Runtime (CLR) deals with references to value types.
When an instance of a value type is converted to a System.Object type or to an interface, the CLR needs to convert the value type to a valid reference type. Memory is allocated on the managed heap and the object is copied over. We need to be aware of this for two reasons: boxing is a very expensive process (copying a whole object from the stack to the heap uses up processor cycles and space on the managed heap) and we now have two objects in memory that can have conflicting states.
Here is a simple example of boxing.
int i = 0;
object obj = (object) i; // i is boxed here
obj = ((int) i) + 3; // changing i on the heap
i += 1; // changing i on the stack
Console.WriteLine(obj.ToString());
Console.WriteLine(i.ToString());
Gives us the result:

Here is a play-by-play of what happens
Step 1: i is placed on the stack

Step 2: i is copied to the heap (boxed) and obj goes on the stack, the value of obj is the memory address of the new object on the heap (a pointer).

Step 3: The value of obj is updated and now contains the value 3
Step 4: i (the one on the stack) is updated and now contains the value 1
Here is a more complex example:
class Class1
{
[STAThread]
static void
{
MyInt test = new MyInt();
test.value = 100;
test.AddOne();
aDelegate
test.AddOne();
}
}
public delegate void aDelegate();
public struct MyInt
{
public int value;
public void AddOne()
{
Console.WriteLine(string.Format("Before: {0}", value.ToString()));
value += 1;
Console.WriteLine(string.Format("After : {0}", value.ToString()));
}
}
Here's the output:

Not the result you were expecting, right? What's going on? Let's walk through what happens. After Main() and args[] are placed on the stack and the Main method begins execution:
Step 1: test is placed on the stack
Step 2: AddOne() is placed on the stack and executed. Changing the value of MyInt.value to 101;
Step 3: AddOne() is removed from the stack and MyInt is boxed (copied) to the heap. Del now points to the heap version of the object.

Step 4: AddOne() is called from the boxed object, updating it's value to 102.
Step 5: AddOne() from the heap is removed.
Step 6: AddOne() from the stack version of MyInt is added to the stack, changing it's value to 102.
Finally: Main is done executing and cleared off the stack. The object left in the heap is ready for Garbage Collection (GC).
Let's make a change to improve the performance of our application and get results that make more sense. If we make MyInt into a reference type, we'll be dealing with one object on the heap and there will be no boxing.
public class MyInt
{
public int value;
public void AddOne()
{
Console.WriteLine(string.Format("Before: {0}", value.ToString()));
value += 1;
Console.WriteLine(string.Format("After : {0}", value.ToString()));
}
}
With this change we get results closer to what we are expecting:
| Before: 100 After : 101 Before: 101 After : 102 Before: 102 After : 103 |
In Conclusion
More unexpected places boxing shows up is when we call ToString() or GetType() on a value type. In this case the method is called through the base object (System.Object) and therefore boxing is required before the method is accessible. Boxing also shows up when we place value objects into an ArrayList() (in which case they are typecast to System.Object). As you can imagine, the boxing process can be very expensive if done repeatedly on a large scale.
Hopefully this article gave you a better understanding of how value types are boxed and what to watch out for when dealing with value types through references like interfaces, delegates, or when they are put in an ArrayList.
Until next time,
-Happy coding
amila sampathPosted May 3, 2012, 6:29 AM
Thank you very much
amila sampathPosted May 3, 2012, 6:29 AM
Thank you very much
amila sampathPosted May 3, 2012, 6:28 AM
Thank you very much
Fabio SoaresPosted May 25, 2011, 9:42 AM
Excellent way of teaching.
Abhishek singhPosted Jun 16, 2006, 12:00 PM
invoking ToString(), will not always cause boxing to occur. Its depends on implementation of value type. If the value type overrides ToString() method, compiler will generate IL to directly call this method without boxing. Most of the .NET BCL value types, like Int32 overrides ToString(), so Int32 counter = 10; string str = counter.ToString(); //NO Boxing For Object.GetType(); it is not a virtual function, so value type can't provide any implementation and any call to GetType() will always be boxed. Regards,
illiopPosted May 9, 2006, 10:41 AM
I am sorry maybe I did not write clearly.I mean if the program is like this : class Class1 { [STAThread] static void Main(string[] args) { MyInt test = new MyInt(); test.value = 100; test.AddOne(); aDelegate del = new aDelegate(test.AddOne); del(); test.AddOne(); } } public delegate void aDelegate(); public class MyInt //change 'struct' to 'class' { public int value; public void AddOne() { Console.WriteLine(string.Format("Before: {0}", value.ToString())); value += 1; Console.WriteLine(string.Format("After : {0}", value.ToString())); } } the result will be : Before: 100 After: 101 Before: 101 After: 102 Before: 102 After: 103 But you say :"With this change we get results closer to what we are expecting:" Before: 100 After: 101 Before: 101 After: 102 Before: 101 After: 102 Am I right ? thank you very much. look forward to your reply.
illiopeditedPosted Apr 21, 2006, 12:09 PMEdited Jun 5, 2006, 3:32 AM
In the articles above,if you change the key word "struct" to "class",the result will be : Before: 100 After: 101 Before: 101 After: 102 Before: 102 After: 103 I run the example program in VS2005.I think the result is right,a class instance will get its space in HEAP,a delagate instance is in fact a reference point to the instace space ,so all the changes is happened on the HEAP (this is not like the "struct" example). wrote by: ace.net