Value and Reference Types
At the core of C#'s type system is one question: where does the data live, and what happens on assignment. Value types (struct, int, bool, enum) hold their value inline and are copied whole; reference types (class, string, arrays) live on the heap while the variable holds a reference — assignment copies the reference, and both variables share one object. This distinction governs the behavior of assignment, method passing, comparison, and performance.
Mistakes here are rarely about syntax — they are about the memory model. A struct passed to a method is copied, so changes are invisible to the caller; a mutable struct in a property or collection mutates a copy, not the original; assigning a value type to object silently boxes it onto the heap and pressures the garbage collector; as on a non-nullable value type is a compile error. Each mechanism, layer by layer, is below.
Topic map
- Value types — hold their data inline (on the stack or inside a container), and assignment copies the whole value.
- Reference types — live on the heap, the variable holds a reference, assignment copies the reference and the object stays shared.
- Struct semantics —
structversusclass, the lack of inheritance, and the mutable-struct traps. - Boxing and unboxing — wrapping a value type in a heap
objectand its cost to the garbage collector. - Type testing —
is,as, and pattern matching for runtime type checking.
Common Mistakes and Traps
| Mistake | Consequence |
|---|---|
| Assuming all objects live on the heap | Local value-type variables are stored inline, often on the stack |
| Expecting a reference-type assignment to copy the object | Only the reference is copied — both variables mutate one object |
Thinking string is a value type | string is a reference type; immutability does not make it a value type |
Mutating a mutable struct field in a collection or property | A temporary copy is changed, not the original — the edit is "lost" |
Assigning a value type to object without noticing boxing | A hidden heap allocation and GC pressure in a hot loop |
Expecting as to throw on failure | as returns null; using it yields a NullReferenceException later |
Using as on a non-nullable value type | Compile error — as works only on reference and nullable types |
Interview relevance
The value-versus-reference distinction is one of the most frequent C# interview questions, because it decides literally all assignment behavior. A candidate who explains it as "a value type is copied whole, a reference type shares one object through a reference" and immediately draws the consequence for method passing demonstrates a working memory model, not a memorized fact.
Typical checks:
- Where a value type is stored, and why "always on the stack" is imprecise (a class field lives on the heap).
- What assignment copies: the whole value versus the reference.
structversusclass— inheritance,null, copy semantics.- What boxing/unboxing is and why it is an implicit heap allocation.
- The difference between
isandasand whyasdoes not work on non-nullable value types.
Common wrong answer: "Value types on the stack, reference types on the heap — that's the whole difference." That opens the discussion that a value type living as a class field is on the heap, that the essence is copy semantics rather than storage location, and that this is what explains the behavior of methods, collections, and boxing.