C#
programming
record vs class vs struct
software development
.NET

When to use record vs class vs struct

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Choosing the appropriate data structure is crucial in C# programming to ensure optimal performance, code clarity, and maintainability. The three common data structures you'll encounter are records, classes, and structs. Each has its own specific use cases, benefits, and limitations. This guide will explore when to use each structure, supported by technical explanations and examples.

Classes

Overview

Classes are reference types and a fundamental concept in object-oriented programming. They are used to model real-world entities and encapsulate data and behavior related to those entities.

Characteristics

  • Reference Type: Classes are always allocated on the heap.
  • Mutable by Default: Instances of classes can be modified unless marked otherwise.
  • Inheritance: Classes support inheritance, allowing the creation of subclasses.
  • Polymorphism: Through interfaces or abstract classes, classes can participate in polymorphic behavior.
  • Garbage Collection: Since they are stored on the heap, garbage collection is responsible for memory management.

Usage

  • Encapsulating Complex Behavior: When your entity requires complex logic or behavior beyond just state representation.
  • Long-lived Objects: For objects that persist over the application's lifetime.
  • Inheritance and Polymorphism: When you need to leverage polymorphic behavior or inheritance.

Example

csharp
1public class Car
2{
3    public string Make { get; set; }
4    public string Model { get; set; }
5
6    public void StartEngine()
7    {
8        // Logic to start the engine
9    }
10}

Structs

Overview

Structs are value types and are typically used for data structures that contain primarily data with little or no behavior.

Characteristics

  • Value Type: Stored on the stack, which can provide performance benefits for small and frequently accessed objects.
  • Immutability: Generally used for immutable objects, although this is not enforced by the language.
  • No Inheritance: Cannot inherit from other structs or classes, but can implement interfaces.

Usage

  • Small Data Structures: For grouping small amounts of data.
  • Performance-Critical Applications: When the overhead of heap allocation is a concern.
  • Immutable Entities: When defining simple, immutable data containers.

Example

csharp
1public struct Point
2{
3    public int X { get; }
4    public int Y { get; }
5
6    public Point(int x, int y)
7    {
8        X = x;
9        Y = y;
10    }
11}

Records

Overview

Records, introduced in C# 9.0, provide a concise syntax for creating immutable reference types, typically used to model immutable data.

Characteristics

  • Immutable by Default: Designed to represent immutable data. The with keyword is often used to create modified copies.
  • Value Equality: Records implement value-based equality, comparing data rather than object reference.
  • Reference Type: Like classes, records are reference types and stored on the heap.

Usage

  • Data Transfer Objects (DTOs): For representing data intended to be passed along different layers or boundaries.
  • Immutability: When you need immutable data structures with concise syntax.
  • Automatic Synthesis: Auto-implemented members and constructors make records succinct and expressive.

Example

csharp
public record Person(string FirstName, string LastName);

Additional Details

Comparing Mutability and Performance

  • Mutability: Classes are mutable, whereas structs are typically used immutably, and records are immutable by default.
  • Performance: Structs offer stack allocation benefits for small data, whereas classes and records involve heap allocation and garbage collection.

Considerations in Multithreading

  • Thread Safety: Immutable types (records) offer inherent thread safety benefits.
  • Synchronization: Mutable classes may require explicit synchronization mechanisms in concurrent environments.

Summary Table

Feature/AspectClassStructRecord
TypeReferenceValueReference
AllocationHeapStackHeap
Default MutabilityMutableTypically immutableImmutable
InheritanceSupportsDoes not supportSupports (since C# 10, after using record class)
EqualityReferenceValueValue
Use CasesEncapsulation, complex entities with behavior, polymorphismSmall data structures immutability, performance-criticalImmutable data transfer, concise syntax

Choosing the right construct—record, class, or struct—depends on the specific requirements of your application, considering factors such as mutability, performance, complexity, and usage pattern. Understanding the nuances of each helps in building efficient and maintainable code.


Course illustration
Course illustration

All Rights Reserved.