What is boxing and unboxing in C#?
Quick Answer
Boxing is wrapping a value type in an object (or interface) reference so it can live on the heap — it happens implicitly when you assign an int to an object. Unboxing is the explicit cast back to the value type. Both cost a heap allocation / copy, so boxing in hot paths and large loops is a performance problem.
Boxing is when a value type gets wrapped in an object reference and moved to the heap — it happens automatically when you assign, say, an int to an object variable. Unboxing is the explicit cast back. Each one is a heap allocation and a copy, so it's cheap once and expensive in a tight loop. The classic place it used to bite people was the old non-generic collections like ArrayList, which store everything as object — that's a big reason generics were added. So the way to avoid it is to use generic collections and generic methods so the value type stays a value type.
Because every type is rooted at object, a value type sometimes has to be treated as a reference. The CLR does this by allocating a box on the heap, copying the value into it, and handing back a reference.
Where it sneaks in:
- Non-generic collections —
ArrayList,Hashtablestoreobject, so everyintyou add is boxed. - String formatting —
string.Format("{0}", 42)boxes (mitigated by interpolation improvements, but still possible). - Calling an interface method on a struct held as the interface type.
object.Equals/ non-genericIComparable.
How to avoid it: use generics (List<int>, Dictionary<int,T>) so the value type is stored directly; implement IEquatable<T> on structs; prefer generic constraints over object parameters. Unboxing also throws InvalidCastException if the target type doesn't exactly match.
int n = 42;
object boxed = n; // boxing: heap allocation + copy
int back = (int)boxed; // unboxing: explicit cast + copy
// hidden boxing in a non-generic collection
var list = new System.Collections.ArrayList();
list.Add(1); // boxed
list.Add(2); // boxed
// no boxing
var fast = new List<int> { 1, 2 };