Truc's NotesVol. 1 (2026)

Use ValueTask<T> in .NET

Truc Nguyen*

AbstractA quick note on when and why to use ValueTask<T> instead of Task<T> in .NET for high-throughput, cache-friendly async APIs.

Keywords:tech · c# · dotnet · async

Use ValueTask<T> when your async method often returns a result synchronously — it avoids unnecessary heap allocations and is faster under load.


The problem with Task<T>

Every Task<T> is a heap-allocated object. For methods that resolve synchronously most of the time (e.g., cache hits), this creates a lot of garbage for no real benefit.

The fix with ValueTask<T>

ValueTask<T> is a struct. When the result is already available, it returns inline — zero allocation.

internal interface ILookupService
{
    ValueTask<IList<LookupModel>> GetCategoriesAsync();
}

When to use it

ScenarioUse
Result often comes from cache (sync)ValueTask<T>
Always awaits I/O (DB, HTTP)Task<T>
Called in loop that service mostly returns sync resultsValueTask<T>

Don't use ValueTask<T> everywhere — only where performance profiling shows benefit

Cite

@misc{nguyen2026:dotnet-value-task,
  author = {Nguyen, Truc},
  title  = {Use ValueTask<T> in .NET},
  year   = {2026},
  url    = {https://tructn.github.io/blog/dotnet-value-task},
  note   = {Truc's Notes}
}

← All articles