What is the difference between a value type and a reference type?
Quick Answer
A value type (struct, enum, int, bool, DateTime) holds its data directly; assigning or passing it copies the value. A reference type (class, interface, array, delegate, string) holds a reference to an object on the heap; assigning or passing it copies the reference, so both variables point to the same object.
A value type holds its data directly, so when you assign it or pass it to a method you get a copy — changing the copy doesn't affect the original. A reference type holds a reference to an object on the heap, so assigning it copies the reference and both variables point at the same object. Structs, enums and the built-in numeric types are value types; classes, arrays, delegates and string are reference types. The default for a value type is a zeroed value and it can't be null unless you use the nullable form like int?; the default for a reference type is null. I reach for a struct only when the data is small, immutable and value-like — otherwise a class.
Storage. Value-type instances live wherever they are declared — inline in a local (stack) or inside their containing object (heap). Reference-type objects always live on the managed heap; the variable holds a pointer.
Copy semantics.
var b = a;for a struct copies all fields —bis independent.- For a class,
bandarefer to the same instance; a change through one is visible through the other.
Defaults & nullability. A value type's default is a zeroed instance (0, false); it can't be null unless wrapped as Nullable<T> (int?). A reference type's default is null.
Equality. Structs compare field-by-field by default (though you should override for performance/correctness); classes compare by reference unless Equals/== are overridden (records do this for you).
When to use a struct: small (roughly ≤ 16 bytes), immutable, short-lived, value-like data (a point, a money amount). Otherwise use a class — large structs are expensive to copy and passing them around defeats the purpose.
struct PointS { public int X; }
class PointC { public int X; }
var s1 = new PointS { X = 1 };
var s2 = s1; // copy
s2.X = 99; // s1.X is still 1
var c1 = new PointC { X = 1 };
var c2 = c1; // same object
c2.X = 99; // c1.X is now 99