0Pricing
C# Academy · Lesson

ValueTask & Avoiding Allocations

Use ValueTask to reduce heap allocations in hot paths, understand its constraints, and avoid common misuse pitfalls.

The Allocation Problem with Task

Task<T> is a reference type — every async method allocates a Task on the heap, even if the result is available synchronously (e.g., from a cache). In hot paths this can cause significant GC pressure. ValueTask<T> solves this.

What Is ValueTask?

ValueTask<T> is a struct that can represent either a synchronously available result or a pending async operation. When the result is synchronous, no heap allocation is needed.

// Task<T>: always allocates, even when result is cached
public async Task<string> GetCached_Task() =>
    _cache.TryGetValue("key", out var v) ? v : await FetchAsync();

// ValueTask<T>: zero allocation when value is cached
public ValueTask<string> GetCached_ValueTask() =>
    _cache.TryGetValue("key", out var v)
        ? ValueTask.FromResult(v)  // no allocation
        : new ValueTask<string>(FetchAsync()); // allocation only when needed

All lessons in this course

  1. IAsyncEnumerable & await foreach
  2. System.Threading.Channels
  3. ValueTask & Avoiding Allocations
  4. ConfigureAwait & Synchronization Context
← Back to C# Academy