Record vs Class in C#: Key Differences and When to Use Each
record is a reference type designed for immutable data with built-in value-based equality, while a class is a reference type typically used for mutable objects with reference-based equality. Records simplify data modeling by automatically providing equality and immutability features, unlike classes which require manual implementation.Quick Comparison
This table summarizes the main differences between record and class in C#.
| Feature | Record | Class |
|---|---|---|
| Type | Reference type with value-based equality | Reference type with reference-based equality |
| Mutability | Immutable by default (with init-only setters) | Mutable by default |
| Equality | Value equality (compares data) | Reference equality (compares object references) |
| Use case | Data models, DTOs, immutable data | General-purpose objects, mutable state |
| Syntax | Concise with positional parameters | Flexible with constructors and fields |
| Inheritance | Supports inheritance, but with restrictions | Full inheritance support |
Key Differences
Records are designed to represent data with an emphasis on immutability and value equality. When you create a record, the compiler automatically generates methods like Equals(), GetHashCode(), and ToString() based on the data members, so two records with the same data are considered equal. This makes records ideal for scenarios like data transfer objects or configuration settings.
In contrast, classes use reference equality by default, meaning two objects are equal only if they refer to the same instance. Classes are mutable by default, allowing you to change their state after creation. You must manually override equality methods if you want value-based equality.
Records also support concise syntax with positional parameters, making them quick to write and read. Classes offer more flexibility for complex behaviors, inheritance, and mutable state management, but require more boilerplate for equality and immutability.
Code Comparison
Here is an example of a record in C# representing a person with immutable properties and value equality.
public record Person(string FirstName, string LastName); class Program { static void Main() { var person1 = new Person("Alice", "Smith"); var person2 = new Person("Alice", "Smith"); System.Console.WriteLine(person1 == person2); // True because of value equality System.Console.WriteLine(person1); // Prints: Person { FirstName = Alice, LastName = Smith } } }
Class Equivalent
The equivalent class version requires manual implementation of equality and is mutable by default.
public class Person { public string FirstName { get; set; } public string LastName { get; set; } public Person(string firstName, string lastName) { FirstName = firstName; LastName = lastName; } public override bool Equals(object obj) { if (obj is not Person other) return false; return FirstName == other.FirstName && LastName == other.LastName; } public override int GetHashCode() => (FirstName, LastName).GetHashCode(); public override string ToString() => $"Person {{ FirstName = {FirstName}, LastName = {LastName} }}"; } class Program { static void Main() { var person1 = new Person("Alice", "Smith"); var person2 = new Person("Alice", "Smith"); System.Console.WriteLine(person1.Equals(person2)); // True because of overridden Equals System.Console.WriteLine(person1); // Prints: Person { FirstName = Alice, LastName = Smith } } }
When to Use Which
Choose record when you want simple, immutable data containers with automatic value equality, such as for data transfer objects, configuration, or any data where identity is based on content.
Choose class when you need mutable objects, complex behavior, or full control over inheritance and lifecycle, such as for business logic, UI components, or entities with identity beyond data.