Choosing a type

1 min read
On trails:CSTYPESstep 6/6

The kind of type follows from what the thing is.

  • A class has identity, changing state or inheritance, such as a customer or a service. EF Core entities belong here: its guidance is to avoid records for them, because it tracks entities by reference equality.
  • A record is its data, so two with the same values are the same thing, such as an address or a DTO. It has value equality, with and ToString. The positional or property form is a separate choice (see the () and noteRecords: the () way and the {} wayA record can be declared with its data in parentheses or in a body.Opens in a new tab).
  • A struct is a small, immutable single value, preferably readonly. A readonly record struct adds value equality and with.
  • An interface is a contract that unrelated types can fulfil. An abstract class adds shared behavior (see interfaces versus abstract classesInterfaces versus abstract classesTwo ways to define what a type must offer, and when each one fits.Opens in a new tab).
Kind Copying Equality by default Inheritance
class Reference Shares the object Reference One base class, plus interfaces
struct Value Copies the value Compares fields Interfaces only
interface Contract Not applicable Not applicable Implemented by many types
record Reference Shares, and with makes a copy By value One base record, plus interfaces
record struct Value Copies the value By value Interfaces only

A wrong choice shows up later as a copy that wasn’t independent, an equality check that returns false, or an allocation on a hot path (see value types and reference typesValue 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).