DEV Community

Theodore Karropoulos
Theodore Karropoulos

Posted on • Edited on

Exploring C# Custom Types: Understanding Records, Structs, and Classes

Introduction

As developers, we daily encounter the need to organize and manage data in our applications. Whether we are modeling complex entities, representing simple data structures, or ensuring data immutability, choosing the right construct is crucial. C# provides three primary user-defined types to help us with these tasks, classes, structs, and records. Each of these types has its unique characteristics and use cases, allowing us to tailor our approach to the specific needs of our code.

What is a class?

A class is a blueprint for creating objects. It defines a type that can have fields, properties, methods. Classes are reference types and they are stored on the heap memory and their variables hold references to the actual data. Lets better look an example on how we are using a class.

Example

// Definition
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public void Log()
    {
        Console.WriteLine($"Hello, my name is {FirstName} {LastName}");
    }
}

// Usage
Person person = new Person { FirstName = "Jane", LastName = "Smith" };
person.Log();
Enter fullscreen mode Exit fullscreen mode

What is a Struct?

A struct is a value type and their storage depends on the context in which they are used. While structs are often associated with the stack, they are not always stored there. When we declare a struct as a local variable within a method, it is typically stored on the stack, for example

void SomeMethod()
{
    Point point = new Point(5, 10); // point here is stored on the stack
Enter fullscreen mode Exit fullscreen mode

When a struct is a field of a class, it is stored on the heap along with the containing class instance, for example

public class SomeClass
{
    public Point point; // point is stored on the heap with the SomeClass instance
}

SomeClass someClassInstance = new SomeClass();
Enter fullscreen mode Exit fullscreen mode

When structs are elements of an array, the array itself is an object on the heap, so the structs are stored on the heap, for example

Point[] points = new Point[10]; // points array and its elements are stored on the heap
Enter fullscreen mode Exit fullscreen mode

Structs are typically used for small and simple objects and used to represent single values. Like classes structs may also have
fields, properties and methods. The main difference between and a struct is that a struct do not support inheritance. Lets give an example on how we can use a struct type.

Example

// Definition
public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }

    public void Print()
    {
        Console.WriteLine($"Point at ({X}, {Y})");
    }
}

// Usage
Point point = new Point { X = 5, Y = 10 };
point.Print(); 
Enter fullscreen mode Exit fullscreen mode

What is a Record?

Records are a new type introduced in C# 9.0, designed to simplify working with immutable data. Like classes, records are reference types, but they come with built-in support for value-based equality and immutability, making them a powerful tool for managing data in a clean and intuitive way.

Example

// Definition
public record Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }

    public void Log()
    {
        Console.WriteLine($"Hello, my name is {FirstName} {LastName}.");
    }
}

// Usage
var person = new Person { FirstName = "Jane", LastName = "Smith" };
person.Log();
Enter fullscreen mode Exit fullscreen mode

When to Use Each

  • Class, use when you need a complex object that might require inheritance, mutable state or shared references
  • Struct, use for small and simple objects that represent single values, especially when performance is critical
  • Records, use them when you need an immutable object that is primarily defined by its data. Ideal for DTO (data transfer objects)

Comparing Class, Struct, and Record

Feature Class Struct Record
Type Reference Value Reference
Storage Heap Stack Heap
Inheritance Yes No Yes
Immutability Mutable by default Mutable by default Immutable by default
Equality Reference-based Value-based Value-based
Usage Complex objects Small data structures Immutable data structures

Top comments (0)