Boxing vs Unboxing in C#: Understanding the Hidden Performance Cost

As C# developers, we often work with both value types (such as int, bool, and double) and reference types.

Most of the time, .NET handles the conversion between them automatically. However, these conversions come with a cost that every developer should understand.

This is where boxing and unboxing come into play.

What Is Boxing?

Boxing is the process of converting a value type into a reference type (object or an interface it implements).

When boxing occurs, the CLR creates a new object on the managed heap and copies the value into it.

Example:

int number = 100;

object obj = number;   // Boxing

Here, number is copied from the stack into a new object on the heap.


What Is Unboxing?

Unboxing is the reverse process.

It extracts the value type from the boxed object.

Example:

object obj = 100;

int number = (int)obj;   // Unboxing

Notice that unboxing requires an explicit cast.

If the boxed object isn’t the expected type, an InvalidCastException will be thrown.

Example:

object obj = 100;

double value = (double)obj;   // Throws InvalidCastException

Why Does Boxing Matter?

Boxing may look harmless, but it has hidden costs:

  • Allocates memory on the heap
  • Copies the value
  • Increases garbage collection pressure
  • Reduces performance when performed repeatedly

Consider this loop:

ArrayList list = new ArrayList();

for (int i = 0; i < 100000; i++)
{
    list.Add(i);   // Boxing on every iteration
}

Every integer is boxed before being stored.

Using a generic collection avoids this overhead:

List<int> numbers = new List<int>();

for (int i = 0; i < 100000; i++)
{
    numbers.Add(i);
}

No boxing occurs because List<int> stores integers directly.


Common Scenarios That Cause Boxing

  • Assigning a value type to object
  • Using non-generic collections like ArrayList
  • Passing value types where an object parameter is expected
  • Some interface conversions

How to Avoid Boxing

✔ Prefer generic collections (List<T>, Dictionary<TKey, TValue>)

✔ Use generic methods instead of methods accepting object

✔ Avoid unnecessary casts

✔ Profile performance before optimizing


Interview Tip

A common interview question is:

Why are generic collections faster than ArrayList?

The answer:

Generic collections store value types directly, avoiding boxing and unboxing operations. This results in fewer heap allocations, less garbage collection, and better performance.


Final Thoughts

Boxing and unboxing are fundamental concepts in C#. Although modern .NET has become highly optimized, unnecessary boxing can still impact performance in high-frequency code paths.

Understanding when boxing occurs helps you write cleaner, faster, and more efficient applications.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *