C#  

Working with Span, Memory, and ref structs in High-Performance Apps using .NET 9

Introduction

In modern high-performance applications, reducing memory allocations and improving execution speed is critical. .NET 9 continues to enhance low-level memory handling using:

  • Span

  • Memory

  • ref struct

These features allow developers to write allocation-free, high-speed code, especially useful in:

  • Real-time systems

  • Financial apps

  • Game engines

  • APIs handling large data

Why These Concepts Matter

Traditional approaches (like arrays and strings) often:

  • Allocate memory on heap

  • Increase GC pressure

  • Reduce performance

Span and Memory solve this by working with stack or managed memory efficiently without copying data.

1. Span – Fast Stack-Based Memory Access

Key Points

  • Works on stack memory

  • No heap allocation

  • Can point to arrays, strings, or unmanaged memory

  • Defined as a ref struct

Example

public static void SpanExample()
{
    int[] numbers = { 1, 2, 3, 4, 5 };

    Span<int> span = numbers;

    span[0] = 100;

    Console.WriteLine(numbers[0]); // Output: 100
}

Benefits

  • No extra memory allocation

  • Faster than copying arrays

  • Safe (bounds-checked)

Limitations

Cannot be used in:

  • async methods

  • iterators (yield)

  • stored in heap

2. Memory – Heap-Friendly Alternative

Key Points

  • Works with heap memory

  • Can be used in async methods

  • More flexible than Span

Example

public static async Task MemoryExample()
{
    int[] numbers = { 10, 20, 30 };

    Memory<int> memory = numbers;

    await Task.Delay(100);

    memory.Span[0] = 999;

    Console.WriteLine(numbers[0]); // Output: 999
}

Span vs Memory

  • Feature: Span | Memory

  • Allocation: Stack | Heap

  • Async Support: No | Yes

  • Performance: Very Fast | Fast

  • Flexibility: Limited | More Flexible

3. ref struct – The Backbone

What is ref struct?

A ref struct:

  • Lives only on the stack

  • Cannot be boxed

  • Cannot implement interfaces

Span itself is a ref struct.

public ref struct MyBuffer
{
    private Span<int> _data;

    public MyBuffer(Span<int> data)
    {
        _data = data;
    }

    public void SetFirst(int value)
    {
        _data[0] = value;
    }
}

Real-World Use Case

Scenario: High-Performance String Parsing

Traditional Approach

string data = "apple,banana,grape";
var parts = data.Split(',');

Creates multiple string allocations.

Optimized with Span

ReadOnlySpan<char> span = "apple,banana,grape".AsSpan();

int index = span.IndexOf(',');

var first = span.Slice(0, index);

Console.WriteLine(first.ToString()); // apple

No extra allocations until ToString().

Performance Impact

Using Span and Memory can:

  • Reduce GC pressure drastically

  • Improve throughput

  • Lower latency in APIs

When to Use What?

  • Synchronous high-performance: Span

  • Async or long-lived data: Memory

  • Custom stack-only structures: ref struct

Common Mistakes

  • Using Span in async methods

  • Returning Span from methods incorrectly

  • Converting to string too early (loses benefit)

Interview Questions

  • What is the difference between Span and Memory?

  • Why is Span a ref struct?

  • Can Span be used in async methods? Why not?

  • How does Span reduce GC pressure?

  • When would you prefer Memory over Span?

Conclusion

In .NET 9, mastering Span, Memory, and ref struct gives you a huge performance advantage.

These are not beginner features — they are senior-level tools used in:

  • High-performance APIs

  • System-level programming

  • Libraries and frameworks