Task allocates even when result is immediately available. ValueTask avoids allocation for synchronous returns.
Scenario:
// Cache that often has value ready (no async needed) public async TaskGetUserAsync(int id) { if (_cache.TryGetValue(id, out var user)) return user; // Immediate return, but still allocates Task return await _db.Users.FindAsync(id); }
Better with ValueTask:
public async ValueTaskGetUserAsync(int id) { if (_cache.TryGetValue(id, out var user)) return user; // No allocation when cached! return await _db.Users.FindAsync(id); }
When to Use:
– Method often returns synchronously (cache hits)
– High-frequency calls (called millions of times)
– Performance-critical code
When NOT to Use:
– Method always awaits
– Result needs to be stored/passed around
