Object, Boxing/Unboxing, Generics
Short, interview-ready summary.
Memory hook
"Object = base of all reference types; boxing = value → object; unboxing = object → value; generics = avoid boxing and get type safety"
System.Object (base type)
- All reference types inherit from object (alias Object)
- Value types are boxed when assigned to object
Common members
Equals(object? obj) // equality
GetHashCode() // hash for dictionaries/hash sets
ToString() // string representation
GetType() // runtime type
- ReferenceEquals(a, b) — same reference (or both null)
- Override Equals and GetHashCode together; use same fields for hash
Boxing and unboxing
Boxing (value → reference)
int i = 42;
object o = i; // box: value copied to heap, o refers to box
- Value is copied to heap; variable holds reference to box
- Has cost (allocation, copy)
Unboxing (reference → value)
object o = 42;
int i = (int)o; // unbox: value copied from box to i
- Must cast to exact value type; wrong type → InvalidCastException
- Unboxing copies value out of the box
Why it matters
- Boxing/unboxing in loops or hot paths can hurt performance
- Generics (e.g. List<int> instead of ArrayList) avoid boxing for value types
Generics
"Generic type = type parameterized by T; no boxing for value types; type safety at compile time"
public class Cache<T>
{
private T? _value;
public T? Get() => _value;
public void Set(T value) => _value = value;
}
var intCache = new Cache<int>(); // T = int, no boxing
var strCache = new Cache<string>(); // T = string
Constraints
public void Copy<T>(T source) where T : class { }
public void Compare<T>(T a, T b) where T : IComparable<T> { }
public T Create<T>() where T : new() { return new T(); }
- where T : class — reference type
- where T : struct — value type (non-nullable)
- where T : IComparable<T> — implements interface
- where T : new() — parameterless constructor
Benefits
- No boxing for List<int>, Dictionary<int, string>, etc.
- Compile-time type safety
- One implementation for all T
Interview one-liner
"object is the base type for reference types; value types are boxed when assigned to object. Boxing allocates and copies; unboxing requires an exact cast. Generics avoid boxing for value types and give compile-time type safety; use constraints (where T : ...) when you need to call methods on T."
Cheat sheet
object = base of ref types; value types box when assigned
Boxing = value → heap; unboxing = (T)obj, exact type
Generics = List<T>, no boxing, type safe
where T : class | struct | IComparable<T> | new()