the quick notes

fast, quirky, and occasionally buggy: where tech meets sticky notes!

use ValueTask<T> in .NET

🇬🇧
techc#dotnetasync

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