Structs, Enums & Record Structs Masterclass

โšก C# 12 & .NET 8 ๐ŸŸข Chapter 19 of 35 ๐Ÿ“‚ Phase 7: Advanced C# Language ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: struct ยท Struct vs Class ยท Stack Memory ยท enum ยท Enum Switch ยท record Class ยท record struct ยท Value Equality ยท Immutable Models

Welcome to Phase 7 (Chapter 19): C# Structs, Enums & Records Masterclass! Choosing the right data structure directly impacts application memory consumption and performance. In this chapter, we master struct value-type behavior, enum strongly typed enumerations, record classes, C# 10 record struct, value-based equality, immutable data modeling, and guidelines for choosing between class, struct, or record.

1Structs & Value-Type Behavior (Struct vs Class)

A struct is a light-weight Value Type stored directly on the Stack (or inside its containing object). Unlike classes, assigning a struct variable to another variable copies the entire data byte-by-byte rather than copying a heap memory reference pointer.

PropertyClass (Reference Type)Struct (Value Type)Record (Reference / Value)
Memory LocationHeap (Pointer on Stack)Stack (Direct data allocation)Heap (Record Class) / Stack (Record Struct)
Assignment BehaviorReference Copy (Shares object)Value Copy (Independent clone)Value Copy or Reference Copy
Equality CheckReference Equality (by default)Value Equality (compares fields)Automatic Value Equality
InheritanceSupports Class InheritanceNo Struct Inheritance (Interfaces only)Record Class inheritance supported
Best Used ForComplex entities with state & logicSmall lightweight value containers (<16 bytes)Immutable Data Transfer Objects (DTOs)
C# โ€” Struct Definition & Value Copying โ–ถ Run in Compiler
public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }

    public override string ToString() => $"Point({X}, {Y})";
}

// Value Type Copy Behavior Demonstration
Point p1 = new Point(10, 20);
Point p2 = p1; // COPIES ACTUAL VALUES (Independent object on Stack!)
p2.X = 99;

Console.WriteLine($"p1: {p1}"); // Point(10, 20) โ€” p1 remains unchanged!
Console.WriteLine($"p2: {p2}"); // Point(99, 20)
2Enums โ€” Strongly Typed Constants

An enum (enumeration) defines a strongly typed set of named integer constants, eliminating magic numbers and magic strings across your codebase.

C# โ€” Enum with Switch Statement โ–ถ Run in Compiler
enum OrderStatus
{
    Pending = 1,
    Processing,
    Shipped,
    Delivered,
    Cancelled
}

OrderStatus status = OrderStatus.Processing;

// Enum with Switch Expression
string message = status switch
{
    OrderStatus.Pending    => "Order received and waiting for payment.",
    OrderStatus.Processing => "Order is being packed in the warehouse.",
    OrderStatus.Shipped    => "Order is out for delivery with courier.",
    OrderStatus.Delivered  => "Order delivered successfully!",
    _                      => "Order status unknown."
};

Console.WriteLine($"Status: {status} (Code: {(int)status}) -> {message}");
3Record Classes & Record Structs

C# 9+ introduced Records to model immutable data with positional parameters, non-destructive mutation (the with expression), and automatic value-based equality.

C# โ€” Record Class vs Record Struct โ–ถ Run in Compiler
// 1. Record Class (Reference Type with Value Equality)
public record Product(int Id, string Name, decimal Price);

// 2. Record Struct (Value Type with Record features โ€” C# 10+)
public readonly record struct GeoLocation(double Latitude, double Longitude);

Product prod1 = new(101, "Laptop", 75000.00m);
Product prod2 = new(101, "Laptop", 75000.00m);

// Value-based equality check
Console.WriteLine($"prod1 == prod2: {prod1 == prod2}"); // True!

// Non-destructive mutation using 'with'
Product updatedProd = prod1 with { Price = 69999.00m };
Console.WriteLine($"Updated Product: {updatedProd}");
4Technical FAQs

Q1: When should I choose a Struct over a Class?

Choose a struct when data size is small (<16 bytes), objects are short-lived, immutable, and created frequently inside loops to reduce Garbage Collector allocation pressure.

Q2: What is the underlying type of an enum?

By default, an enum's underlying type is int (32-bit integer). You can override this to byte, short, or long (e.g., enum Status : byte).