Structs and records
A struct is a value type: its variable holds the data itself, so assigning it copies every field. A record is a type the compiler fills in for you: from one line it writes a constructor, init-only properties, value equality, a readable ToString and support for with. Follow one program as a struct is copied and changed, and as record objects land on the heap, get copied with with, print themselves and compare equal by value.
5 quick questions
Pick an answer to see why. Your score saves with your progress.
01Point is a struct. After var b = a; b.X = 9; what is a.X if it started as 1?
A struct is a value type. Assignment copies the whole value, so a and b are independent; changing b.X leaves a.X at 1.
02Coord is declared as record Coord(int X, int Y). Why does r.X = 9; fail to compile?
For a positional record class the compiler makes public init-only properties. To get a changed version, use a with expression such as r with { X = 9 }, which makes a new object.
03What does var s = r with { X = 9 }; do when r is a record?
with is nondestructive mutation: it clones the record (a shallow copy) and then sets the listed properties on the clone.
04r and t are two different Coord record objects, both with X = 1 and Y = 2. What does Console.WriteLine(r == t) print?
Records have value equality: == is true when both have the same type and every field is equal. With a plain class, == compares references and would print False.
05Which is the best fit for a struct?
.NET's design guidelines suggest a struct for small values (under 16 bytes) that act like one value and are mostly immutable. A Point of two ints is 8 bytes.
Glossary
- Value type
- A type whose variables hold the data itself, such as int or any struct. Assigning one copies the value.
- Reference type
- A type whose variables hold a reference to an object on the heap, such as a class or a record class. Assigning one copies the reference, not the object.
- Struct
- A value type you declare with the struct keyword, usually to bundle a few small values, such as a point.
- Record
- A class (or, with record struct, a struct) for which the compiler writes value equality, ToString, with support and, from positional parameters, a constructor and properties.
- Init-only property
- A property with an init accessor: it can be set in an object initializer or constructor, and never after the object is made.
- with expression
- Makes a copy of a record (or struct) with some properties changed, leaving the original as it was.
- Value equality
- Two values are equal when their contents are equal, even if they are separate objects. Records use it; plain classes compare references.
Notes and sources
- Local variables such as a and b usually live on the stack, but that is a detail of the runtime, not of C#. What C# promises is that a value-type variable holds its own copy of the data.
- The #1, #2 and #3 on the references stand for the objects' addresses; you never see or use real addresses in safe C#.
- "record" on its own means "record class". "record struct" (C# 10) makes a value type with the same extras; its positional properties can be changed unless you write "readonly record struct".
- Record equality is value equality: same run-time type and equal values in every field. For a property that holds an object, such as a list, "equal" still means "the same object".
- with makes a shallow copy: the fields are copied as they are, so a field that refers to an object refers to the same object in both copies.
- The program is real C# (C# 10 / .NET 6 or later). Put the eleven lines in Program.cs and dotnet run prints 1, then Coord { X = 9, Y = 2 }, then True.
- Microsoft Learn: Structure types (C# reference)
- Microsoft Learn: Value types (C# reference)
- Microsoft Learn: Reference types (C# reference)
- Microsoft Learn: Records (C# reference)
- Microsoft Learn: Introduction to record types
- Microsoft Learn: with expression
- Microsoft Learn: Equality operators (record types)
- Microsoft Learn: The init keyword
- Microsoft Learn: Choosing between class and struct
- Microsoft Learn: Object and collection initializers
Quiz Unlocks after the last step.