A clear comparison between classes and records in C#

A clear comparison between Class and Record in C#

In today’s C# landscape, developers are continually looking for ways to simplify code while improving maintainability.

That’s where Records, introduced in C# 9, come into play.

But how do they differ from the good old Classes, and when should you choose one over the other? Let’s dive in and explore the differences between these two.

The core differences between Classes and Records

Classes in C#

Classes have been the go-to structure in object-oriented programming for defining complex data types.

They can contain fields, properties, methods, and events, offering full flexibility for encapsulating behavior and state.

public class Person
{
    // Properties
    public string FirstName { get; set; }
    public string LastName { get; set; }
    
    // Constructor
    public Person(
        string firstName, 
        string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    // Overrides
    public override string ToString() 
        => $"{FirstName} {LastName}";
}

// Instance
var person = new Person("John", "Doe");

// Use
Console.WriteLine(person); 
// Outputs: John Doe

Records in C#

Records were introduced to simplify creating immutable data types. While they look similar to classes, they focus more on data immutability and value-based equality, making them perfect for data-centric programming models.

public record Person(string FirstName, string LastName);

// Instance
var person = new Person("John", "Doe");

// Use
Console.WriteLine(person); 
// Outputs: John Doe

Notice the concise syntax and the immutable nature by default. With record, properties are immutable unless explicitly modified.

Key features that make records stand out

Value equality in records

One of the main differences between classes and records is how equality works. In classes, objects are compared by reference, whereas records compare by value.

// CLASS
var person1 = new Person("John", "Doe");
var person2 = new Person("John", "Doe");

Console.WriteLine(person1 == person2); 
// Outputs: False
// RECORD
var record1 = new Person("John", "Doe");
var record2 = new Person("John", "Doe");

Console.WriteLine(record1 == record2); 
// Outputs: True

Immutability by Default

In records, the properties are immutable by default. This means once you create a record, its properties cannot be changed, making it ideal for scenarios where you need safety in data consistency.

var record = new Person("John", "Doe");
// record.FirstName = "Jane"; 
// Compile-time error, cannot modify properties

If needed, you can make a modified copy using the with expression:

var modifiedRecord = record with { 
    FirstName = "Jane" 
};

Console.WriteLine(modifiedRecord); 
// Outputs: Jane Doe

Concise Syntax with Positional Parameters

Records allow you to define properties concisely, especially when working with data-focused types.

public record Address(string Street, string City, string ZipCode);

This reduces boilerplate code, making records an excellent choice for DTOs (Data Transfer Objects).

When to use Classes and when to use Records

Use Classes when you need:

  • Mutable state.
  • Complex behavior beyond storing data.
  • Reference-based equality (e.g., comparing object references).

Use Records when:

  • Your focus is on immutability and value-based equality.
  • You need concise syntax for data-centric models.
  • You want the benefits of immutability with value comparison built-in.

Conclusion

Both classes and records serve vital roles in C# development. Classes offer flexibility and are suitable for a wide range of applications, while records provide a streamlined way to handle immutable data with value-based equality.

Understanding when to use each will help you write more efficient and maintainable code.