8 questions found
What is the difference between a value type and a reference type?
Beginner
Value types (struct, enum, primitives) hold their data directly and are copied on assignment; reference types (class, array, string, delegate) hold a reference to data on the heap, so assignment copies the reference.
int a = 1; int b = a; b++; // a stays 1
var l1 = new List<int>(); var l2 = l1; l2.Add(9); // l1 also has 9
Real-world example
Passing a struct point copies it; passing a class order shares the same instance.
Where are value types and reference types stored?
Beginner
Local value types typically live on the stack; reference-type objects live on the managed heap with the reference on the stack. Value-type fields inside a class live on the heap with the object.
class Box { public int N; } // N lives on the heap inside Box
int local = 5; // stack
Real-world example
Understanding this explains why large structs are costly to copy.
What is boxing and unboxing, and why does it matter?
Intermediate
Boxing wraps a value type in a heap object (implicit); unboxing extracts it (explicit cast). Both allocate/copy and hurt performance in loops.
int n = 42;
object boxed = n; // boxing
int back = (int)boxed; // unboxing
Real-world example
Non-generic ArrayList boxes every int; List<int> avoids it entirely.
When should you define a struct instead of a class?
Intermediate
Use a struct for small, immutable, value-like data (under ~16 bytes) that is copied cheaply and has value semantics; otherwise use a class. Mutable structs are error-prone.
public readonly struct Money(decimal Amount, string Currency);
Real-world example
Coordinates, money, or a date range are natural structs; an entity with identity is a class.
How do nullable value types (int?) work under the hood?
Advanced
int? is Nullable<int>, a struct with HasValue and Value. The compiler lifts operators so null propagates; boxing a null Nullable<T> boxes to a real null reference.
int? x = null;
object o = x; // o is null
int safe = x.GetValueOrDefault();
Real-world example
Mapping a nullable database column to int? preserves 'no value' distinctly from 0.
Why can mutable structs cause subtle bugs?
Advanced
Because structs copy on assignment and when stored in some collections/properties, mutating a copy does not change the original — leading to lost updates. Prefer readonly structs.
struct P { public int X; }
var list = new List<P>{ new P() };
list[0].X = 5; // compile error / would mutate a copy
Real-world example
A mutable struct field on a class property silently discards writes.
What is the difference between value types and reference types in C#, and how does this affect variable assignment?
Beginner
Value types (primitives like int/bool, plus struct and enum) store their actual data directly wherever the variable lives, so assigning one variable to another copies the value -- modifying the copy never affects the original. Reference types (class, array, delegate, interface) store a reference (memory address) to data on the heap, so assigning one variable to another copies just the reference, meaning both variables end up pointing at the same underlying object and a change through either one is visible through both.
// Value type: assignment copies the data
int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10 -- unaffected
// Reference type: assignment copies the reference
class Person { public string Name; }
var p1 = new Person { Name = "Alice" };
var p2 = p1;
p2.Name = "Bob";
Console.WriteLine(p1.Name); // "Bob" -- p1 and p2 point to the same object
Real-world example
A bug where updating one object in a list appears to unexpectedly change a completely separate variable is traced to both variables referencing the identical heap object (a reference type), resolved once the developer explicitly clones the object rather than assuming assignment created an independent copy.
Common follow-ups: Why does passing a struct to a method not let that method modify the caller's original value, unless 'ref' is used?;How does boxing turn a value type into something that behaves like a reference type?
Value vs Reference Types;equals()
hashCode() & toString() Contracts
What is boxing and unboxing in C#, and why can excessive boxing hurt performance?
Intermediate
Boxing converts a value type (like an int) into an object, copying the value onto the heap so it can be used anywhere a reference type/object is expected (such as in a non-generic collection); unboxing reverses this, extracting the value type back out of the boxed object via an explicit cast, throwing InvalidCastException if the object doesn't actually contain the expected type -- both operations carry real overhead (an extra heap allocation for boxing, a cast check for unboxing), and doing this repeatedly (like storing many ints in an old-style ArrayList) generates unnecessary garbage collection pressure that generic collections avoid entirely.
int num = 10;
object boxed = num; // boxing: copies 'num' onto the heap
int unboxed = (int)boxed; // unboxing: extracts it back, with an explicit cast
// Avoids boxing entirely by using a generic collection instead of ArrayList
List<int> numbers = new() { 1, 2, 3 }; // ints stay as primitives, no boxing per element
Real-world example
A performance review of a legacy codebase using ArrayList to store thousands of integers finds that switching to the generic List<int> eliminates a boxing allocation on every single insertion, measurably reducing GC pauses under load.
Common follow-ups: Why does the .NET small-integer cache concept (relevant in some other languages) not apply the same way to C# boxing?;What specific collection types should be preferred specifically to avoid boxing overhead?
Value vs Reference Types;Garbage Collection