Classes vs Structs vs Records (Which to use when?)
On this page
Classes vs Structs vs Records
Modern C# introduced Records, adding a third major type to our toolkit. Choosing the wrong container for your data can lead to memory leaks, performance bottlenecks, or confusing bugs in concurrent applications.
1. Classes: The Heavyweights (Reference Types)
Classes live on the Heap. They are mutable by default and use Reference Equality.
- Use Case: Entities with identity (Users, Orders, Blogs).
- Equality: Checking if they point to the same memory slot.
2. Structs: The Speedsters (Value Types)
Structs live on the Stack. They are copied by value and usually small.
- Use Case: Primitive-like data (Coordinate, Color, Money).
- Equality: Checking if the bit-values match.
3. Records: The Modern DTO (C# 9+)
Records are essentially classes with "Value-based Equality" built-in. They are designed for Immutability.
// The most concise code in .NET
public record UserDto(string Name, string Email);
var u1 = new UserDto("Sandeep", "s@s.com");
var u2 = new UserDto("Sandeep", "s@s.com");
// This prints TRUE because the data matches, even though they are separate objects!
Console.WriteLine(u1 == u2);
4. Interview Mastery
Q: "What is 'With Expression' in Records, and how does it implement Non-Destructive Mutation?"
Architect Answer: "Because records are usually immutable (`init-only`), you cannot change a property once it’s set. If you want a copy of a record with just one small change, you use the `with` keyword: `var updatedUser = oldUser with { Email = 'new@email.com' };`. This creates a brand-new object in memory, copies all existing properties over, and applies the single modification. This pattern is essential for thread-safety, as you never have to worry about one thread 'mutating' a record while another thread is reading it."