Courses/C#/Unsafe Code & Span<T>
    Back to Course

    Lesson 24: Unsafe Code, Span<T>, and High-Performance C#

    Write zero-allocation code with Span<T>, Memory<T>, ArrayPool, and raw pointers for maximum performance.

    What You'll Learn

    • • Span<T> and ReadOnlySpan<T> for zero-copy slicing
    • • Memory<T> and ArrayPool<T> for heap-safe buffers
    • • Unsafe code blocks, pointers, and the fixed statement
    • • When (and when not) to use these features

    🧠 Real-World Analogy

    Think of Span<T> as a window into a bookshelf — you can see and rearrange books through the window, but you never move the bookshelf itself. unsafe code is like removing the glass entirely: more access, but also more risk.

    Span<T> — Zero-Copy Slicing

    Span<T> is a stack-only type that provides a safe, bounds-checked view over contiguous memory — arrays, strings, or even stack-allocated buffers. It lets you slice and manipulate data without allocating new arrays, which is critical in hot paths.

    Span<T> & ReadOnlySpan<T>

    Slice arrays and strings without allocations using Span.

    Try it Yourself »
    C#
    using System;
    
    class Program
    {
        static void Main()
        {
            // Span<T> — a stack-only view over contiguous memory
            int[] numbers = { 10, 20, 30, 40, 50, 60, 70, 80 };
            
            // Create a span over the entire array (zero-copy!)
            Span<int> fullSpan = numbers.AsSpan();
            Console.WriteLine($"Full span length: {fullSpan.Length}");
            
            // Slice without allocating a new array
            Span<int> middle = fullSpan.Slice(2, 4); // {30, 40, 50, 60}
            C
    ...

    Memory<T> & ArrayPool

    Unlike Span<T>, Memory<T> can be stored on the heap (in fields, async methods, etc.). Combined with ArrayPool<T>, you can eliminate most large array allocations entirely.

    Memory<T> & ArrayPool

    Use heap-safe Memory<T> and ArrayPool to eliminate GC pressure.

    Try it Yourself »
    C#
    using System;
    using System.Buffers;
    
    class Program
    {
        static void Main()
        {
            // Memory<T> — like Span<T> but can live on the heap
            int[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            Memory<int> memory = data.AsMemory();
            
            // Slice without copying
            Memory<int> slice = memory.Slice(3, 4);
            Console.WriteLine($"Slice: [{string.Join(", ", slice.ToArray())}]");
            
            // Convert to Span when you need to work with the data
            Span<int
    ...

    Unsafe Code & Pointers

    C# allows raw pointer manipulation in unsafe blocks. You must compile with /unsafe flag. Use fixed to pin managed objects so the GC won't move them while you're using pointers. This is primarily used for interop with native libraries or extreme performance optimization.

    Unsafe Pointers & fixed Statement

    Use raw pointers, pointer arithmetic, and stackalloc in unsafe blocks.

    Try it Yourself »
    C#
    using System;
    using System.Runtime.InteropServices;
    
    class Program
    {
        // Mark the method as unsafe to use pointers
        static unsafe void Main()
        {
            // Pointer to a stack variable
            int value = 42;
            int* ptr = &value;
            Console.WriteLine($"Value via pointer: {*ptr}");
            
            // Pointer arithmetic with arrays
            int[] array = { 10, 20, 30, 40, 50 };
            fixed (int* p = array) // Pin the array so GC won't move it
            {
                for (int i =
    ...

    Pro Tip

    Prefer Span<T> over unsafe pointers in almost all cases. Span gives you bounds checking and safety while matching pointer performance. Reserve unsafe for P/Invoke or truly specialized scenarios.

    Common Mistakes

    • • Returning Span<T> from a method that uses stackalloc — the memory is gone when the method returns
    • • Forgetting to return rented arrays to ArrayPool — causes memory leaks
    • • Using unsafe when Span<T> would suffice — adds complexity without benefit

    Lesson Complete!

    You've mastered Span, Memory, ArrayPool, and unsafe pointers. Next, learn to manage resources correctly with IDisposable.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service