C# Structs

A struct (short for structure) is a value type that groups related data together — similar to a class, but with key differences in how it is stored and copied in memory. Structs are best used for small, simple data containers.

Struct vs Class

┌────────────────────────────────┬────────────────────────────────┐
│ Class                          │ Struct                         │
├────────────────────────────────┼────────────────────────────────┤
│ Reference type                 │ Value type                     │
├────────────────────────────────┼────────────────────────────────┤
│ Stored on the heap             │ Stored on the stack            │
├────────────────────────────────┼────────────────────────────────┤
│ Assigned = both point to same  │ Assigned = full copy made      │
│ object (shared reference)      │ (independent copy)             │
├────────────────────────────────┼────────────────────────────────┤
│ Can be null                    │ Cannot be null (normally)      │
├────────────────────────────────┼────────────────────────────────┤
│ Supports inheritance           │ Cannot be inherited            │
├────────────────────────────────┼────────────────────────────────┤
│ Best for complex objects       │ Best for small data bundles    │
└────────────────────────────────┴────────────────────────────────┘

Defining a Struct

Use the struct keyword. Struct syntax looks almost identical to class syntax.

struct Point
{
    public int X;
    public int Y;
}

struct Color
{
    public byte R;
    public byte G;
    public byte B;
}

Creating and Using Struct Instances

struct Point
{
    public int X;
    public int Y;
}

class Program
{
    static void Main()
    {
        Point p;
        p.X = 10;
        p.Y = 20;
        Console.WriteLine("X=" + p.X + ", Y=" + p.Y);  // X=10, Y=20

        // Or using new:
        Point origin = new Point();  // X=0, Y=0 (default values)
        Console.WriteLine(origin.X);  // 0
    }
}

Struct with Constructor and Methods

struct Rectangle
{
    public double Width;
    public double Height;

    public Rectangle(double width, double height)
    {
        Width  = width;
        Height = height;
    }

    public double Area()
    {
        return Width * Height;
    }

    public double Perimeter()
    {
        return 2 * (Width + Height);
    }

    public void Display()
    {
        Console.WriteLine($"Rectangle {Width}x{Height}");
        Console.WriteLine($"Area: {Area()}, Perimeter: {Perimeter()}");
    }
}

class Program
{
    static void Main()
    {
        Rectangle r = new Rectangle(5, 3);
        r.Display();
        // Rectangle 5x3
        // Area: 15, Perimeter: 16
    }
}

Value Type Behavior — Copy on Assign

Assigning one struct to another creates a complete, independent copy. Changes to the copy do not affect the original.

struct Point
{
    public int X;
    public int Y;
}

Point a = new Point();
a.X = 5;
a.Y = 10;

Point b = a;   // b gets a COPY of a
b.X = 99;      // modify b

Console.WriteLine(a.X);  // 5  — a is unchanged
Console.WriteLine(b.X);  // 99 — b is separate

Copy Behavior Diagram

┌──────────────────────────────────────────────────────────────┐
│  STRUCT (value type) — copy on assign                        │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Point a = { X=5, Y=10 }                                     │
│                │                                             │
│                ▼  b = a   (full copy made)                   │
│  Point b = { X=5, Y=10 }   ← independent copy                │
│                                                              │
│  b.X = 99                                                    │
│  b → { X=99, Y=10 }                                          │
│  a → { X=5, Y=10 }   ← a unchanged                           │
│                                                              │
├──────────────────────────────────────────────────────────────┤
│  CLASS (reference type) — shared reference                   │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Car a = new Car() { Model="X" }                             │
│  Car b = a;              ← b points to SAME object as a      │
│  b.Model = "Y";                                              │
│  a.Model → "Y"           ← a also changed!                   │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Struct Restrictions

┌────────────────────────────────────────────────────────────┐
│  Struct Limitations:                                       │
│  ❌ Cannot inherit from another struct or class            │
│  ❌ Cannot be a base class                                 │
│  ❌ Cannot have a parameterless constructor (before C# 10) │
│  ❌ Cannot have field initializers (before C# 10)          │
│  ✅ Can implement interfaces                               │
│  ✅ Can have constructors with parameters                  │
│  ✅ Can have methods, properties, indexers                 │
└────────────────────────────────────────────────────────────┘

Struct with Properties

struct Temperature
{
    private double _celsius;

    public double Celsius
    {
        get { return _celsius; }
        set { _celsius = value; }
    }

    public double Fahrenheit
    {
        get { return _celsius * 9 / 5 + 32; }
    }

    public Temperature(double celsius)
    {
        _celsius = celsius;
    }
}

class Program
{
    static void Main()
    {
        Temperature t = new Temperature(100);
        Console.WriteLine(t.Celsius);      // 100
        Console.WriteLine(t.Fahrenheit);   // 212
    }
}

Real-World Uses of Struct

┌────────────────────────────────────────────────────────────┐
│  Common struct uses in C# and .NET:                        │
├────────────────────────────────────────────────────────────┤
│  Point    → X and Y coordinates                            │
│  Color    → R, G, B, A values                              │
│  DateTime → date and time data                             │
│  Guid     → unique identifier                              │
│  decimal  → financial precision number                     │
│  int, double, bool → these are all structs in .NET!        │
└────────────────────────────────────────────────────────────┘

When to Use Struct vs Class

Use STRUCT when:
✅ Data is small (2–4 fields)
✅ The data is logically a single value (like a coordinate)
✅ Instances are short-lived and frequently created
✅ You want copy-on-assign behavior (immutable-ish data)
✅ No need for inheritance

Use CLASS when:
✅ Data is complex with many fields
✅ You need inheritance or polymorphism
✅ Objects have identity (same object shared in multiple places)
✅ The type needs to support null
✅ Object lifetimes are long or managed by garbage collector

Quick Summary

┌─────────────────────────────────────────────────────────────┐
│  struct keyword    → defines a value type                   │
│  Stack-allocated   → faster creation and cleanup            │
│  Copied on assign  → changes to copy don't affect original  │
│  Cannot inherit    → no class hierarchy                     │
│  Can have:         → fields, constructors, methods, props   │
│  Best for:         → small data like coordinates, colors    │
└─────────────────────────────────────────────────────────────┘

Structs are a lean, efficient way to bundle related values together. Every primitive type in C# — int, double, bool — is actually a struct under the hood. Knowing when to choose struct over class is a sign of a developer who thinks about both correctness and performance.

Leave a Comment

Your email address will not be published. Required fields are marked *