0
0
CsharpConceptBeginner · 4 min read

What is ValueTask in C#: Explanation and Usage

ValueTask in C# is a lightweight alternative to Task for asynchronous operations that may complete synchronously or asynchronously. It helps reduce memory allocations by avoiding creating a new Task object when the result is already available.
⚙️

How It Works

Imagine you ask a friend for a quick answer. Sometimes they know it immediately and tell you right away. Other times, they need to check and get back later. ValueTask works like this friend: it can hold a result ready now or promise to deliver it later.

Normally, asynchronous methods return a Task, which always creates an object even if the result is ready immediately. ValueTask can either wrap a Task or directly hold the result value, saving memory and improving speed when the result is already known.

This makes ValueTask useful when you want to avoid the cost of creating many Task objects in high-performance scenarios.

💻

Example

This example shows a method that returns a ValueTask<int>. It returns a completed result immediately if the input is zero; otherwise, it simulates an asynchronous delay.

csharp
using System;
using System.Threading.Tasks;

class Program
{
    static async ValueTask<int> GetNumberAsync(int input)
    {
        if (input == 0)
        {
            // Return synchronously completed result
            return 42;
        }
        else
        {
            // Simulate async work
            await Task.Delay(100);
            return input * 2;
        }
    }

    static async Task Main()
    {
        int result1 = await GetNumberAsync(0);
        Console.WriteLine($"Result when input is 0: {result1}");

        int result2 = await GetNumberAsync(5);
        Console.WriteLine($"Result when input is 5: {result2}");
    }
}
Output
Result when input is 0: 42 Result when input is 5: 10
🎯

When to Use

Use ValueTask when your asynchronous method often completes synchronously and you want to avoid the overhead of creating a Task object every time. This is common in high-performance or low-latency applications like networking, caching, or I/O operations.

However, if your method mostly completes asynchronously or you don't care about small performance gains, using Task is simpler and safer.

Remember, ValueTask has some usage rules: it should only be awaited once and not stored or combined with other tasks, so use it only when you understand these constraints.

Key Points

  • ValueTask can hold a result immediately or a Task for later completion.
  • It reduces memory allocations when results are often ready synchronously.
  • Use it in performance-critical async methods that complete quickly.
  • Follow usage rules: await once, avoid storing or multiple awaits.
  • For most cases, Task remains simpler and preferred.

Key Takeaways

ValueTask reduces overhead by avoiding unnecessary Task allocations when results are ready immediately.
Use ValueTask in high-performance async methods that often complete synchronously.
Always await a ValueTask only once and avoid storing it for later reuse.
For general async programming, Task is simpler and safer to use.
Understanding ValueTask helps optimize memory and speed in critical scenarios.