Class vs Struct in C#: When Performance Matters

Class vs Struct in C#: Deep Dive for Developers Who Care About Performance and Design

What if I told you that many C# developers misuse struct and class – not out of ignorance, but because the consequences aren’t immediately obvious? That one innocent choice can silently eat your memory, ruin performance, or break your API contracts?a

Let’s fix that. In this guide, I’ll break down the real-world differences between class and struct in C# through hands-on examples, insights from production systems, and performance considerations that could save your app.

Understanding the Basics: Class vs Struct

Before diving into code, let’s recap what the official definitions say:

  • class is a reference type – stored on the heap, passed by reference.
  • struct is a value type – stored on the stack (usually), passed by value.

This affects how memory is allocated and how data behaves during method calls.

class MyClass
{
    public int Number;
}

struct MyStruct
{
    public int Number;
}

void ChangeNumber(MyClass obj)
{
    obj.Number = 100;
}

void ChangeNumber(MyStruct obj)
{
    obj.Number = 100;
}

var c = new MyClass { Number = 1 };
var s = new MyStruct { Number = 1 };

ChangeNumber(c);
ChangeNumber(s);

Console.WriteLine(c.Number); // Output: 100
Console.WriteLine(s.Number); // Output: 1

Explanation:

  • When ChangeNumber modifies the class instance, it updates the original object.
  • When it modifies the struct, it only updates the local copy.

Memory and Performance Implications

Structs are lighter and faster… sometimes. But they’re not always better.

Memory Behavior – Class vs Struct

When Structs Shine:

  • Small data containers (like Point, Color)
  • Immutable value-like semantics
  • High-performance scenarios avoiding GC pressure

When Classes are Better:

  • You need polymorphism (inheritance/interfaces)
  • The object is large or frequently mutated
  • You pass the object around a lot (minimize copies)
struct Pixel
{
    public byte R, G, B;
}

class Image
{
    public Pixel[] Pixels;
}

If Pixel was a class, you’d allocate thousands of small objects in an image. That’s GC hell. But as a struct, all pixels live in a single array block, which is far more cache-friendly.

Behavior Gotchas That Cost Hours

  1. Structs can’t have parameterless constructors (until C# 10 in .NET 6+ with default).
  2. Boxing: When a struct is cast to object, it’s copied and boxed – introducing heap allocations.
  3. Mutability: Mutable structs behave unexpectedly:
struct Counter { public int Value; public void Increment() => Value++; }

var c = new Counter();
c.Increment(); // Doesn't work as expected if `c` is a property

If c is a property, c.Increment() works on a copy. No increment.

Design Guidelines: When to Use What

When to Use Struct vs Class

Ask yourself:

  • Is this a simple data container? Use struct.
  • Will this participate in inheritance? Use class.
  • Will it be passed around often? Use class (avoid copies).
  • Will I box it or use interfaces? Lean towards class unless profiling says otherwise.
  • Am I performance-tuning hot paths? Profile, then maybe struct.

Microsoft recommends structs:

  • Are <= 16 bytes
  • Are immutable
  • Don’t need reference equality

FAQ: Clarifying Common Confusions

Can structs have methods?

Yes! You can add methods, but they behave differently with mutability.

Are structs always on the stack?

No. They’re on the stack only when local. In arrays or fields of a class, they’re on the heap.

Why is my struct slow?

Maybe it’s being boxed, or copied too much. Structs are fast when used carefully.

Conclusion: Know Your Tools, Build Better Software

Structs and classes are more than syntax. Choosing the wrong one can silently cost you performance or lead to bugs.

Next time you’re defining a data type, pause. Think. Pick with intention.

If this article helped you, leave a comment or check out more deep dives on the blog. Happy coding!

Leave a Reply

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