Class versus struct

1 min read
On trails:CSTYPESstep 2/6

A struct is a value typeValue types and reference typesA value type variable holds the value. A reference type variable holds a reference to an object.Opens in a new tab, and a class is a reference type. Copying a struct makes an independent copy. Copying a class variable gives a second name for the same object.

C#
struct PointStruct { public int X, Y; }class PointClass { public int X, Y; } var s1 = new PointStruct { X = 1, Y = 2 };var s2 = s1;   // a copys2.X = 99;     // s1.X is still 1 var c1 = new PointClass { X = 1, Y = 2 };var c2 = c1;   // the same objectc2.X = 99;     // c1.X is now 99 too

Differences

Default equality compares fields for a struct, which can be slow unless Equals is overridden or the type is a record structRecordsA class for immutable data, with value-based equality generated for you.Opens in a new tab, and compares references for a class. A struct cannot inherit from a class or struct but can implement interfaces. A struct always exists with zeroed fields, where a class variable can be null. A struct cannot have a finalizer.

When a struct fits

Microsoft’s guidance: small (about 16 bytes), logically a single value, immutable, and not boxed often. Point, Coordinates and DateTime fit. A small local struct needs no heap allocation. A large one is costly to copy, and boxing one allocates.

Immutability

A mutable struct is a trap, because changes apply to a copy. readonly struct makes the compiler require read-only fields.

C#
public readonly struct Coordinates{    public double Lat { get; }    public double Lon { get; }     public Coordinates(double lat, double lon) => (Lat, Lon) = (lat, lon);}

Where it matters

A class is the default. A struct pays off for small immutable values created in large numbers, where avoiding the allocation reduces garbage collection work. See choosing a typeChoosing a typeClass, struct, interface, record class or record struct.Opens in a new tab.