ValueTask Explanation in C#

Since 2018, with the arrival of C# 8, we have a type called ValueTask which can replace, in certain scenarios, the Task type that has been in the language since 2005. However, it is likely that you don’t use this type much; let’s see why. 

 

 

1 - When should you use ValueTask?

 

I want to start with the conclusion. When should we use ValueTask<T>? In this case, or rather, this class has one main scenario in mind.

This scenario is when we have multiple implementations of the same method, the majority of which complete synchronously.

 

For example, if you have an interface with 10 implementations, where 7 or 8 complete synchronously. In that case, we use ValueTask<T>. If, for instance, 10, 9, or even 5 of them complete asynchronously, we would use Task. 

This means that you don’t need to migrate all your code to use ValueTask, using Task is just as fine. 

Related to the previous case, we have the case of hot paths, which are parts of code that execute frequently. If this hot path is synchronous, it is also recommended to use ValueTask<T>. A scenario would be if you have 10 implementations and 1 of those is called 95% of the time and is synchronous; that implementation would be the hot path. 

public interface IImplementation
{
    public ValueTask<int> GetValue();
}

public class DefaultImplementation : IImplementation
{
    public ValueTask<int> GetValue()
    {
        return new ValueTask<int>(1);
    }
}

public class D1Implementation : IImplementation
{
    
    public async ValueTask<int> GetValue()
    {
        return await _dependency.GetValue(); //Simulates 3rd party implementation.
    }
}

public class D2Implementation : IImplementation
{
    
    public async ValueTask<int> GetValue()
    {
        return await _dependency.GetValue(); //Simulates 3rd party implementation.
    }
}

Because of how ValueTask works internally, it does not create a new Task object, which reduces the load on the garbage collector and memory usage.  This is always good.

 

For all other scenarios, use Task.

 

 

2 - Warnings about using ValueTasks

Technically, ValueTask is a union type of Task and T, which means it can only be consumed once.

So, you should not do this:

ValueTask<int> response = implementation.GetValue();

int value1 = await response;
int value2 = await response;

Because, most likely, if you do this an exception will be thrown, since once you await a ValueTask, the object is recycled and it will cause problems. 

 

While if you use Task, it is possible to await multiple times without breaking your code.

 

It is important to remember that ValueTask is a struct, which means we are working with a value type and everything that comes with that. By contrast, Task is a reference type with only one internal field. Why does this matter? Because when using ValueTask, there are more details and data to manage, and this can affect the size and performance of generated code in some scenarios.

 

As a general rule, you should use Task. However, if you are considering using ValueTask, it is best to run multiple benchmarks to ensure it is actually the most suitable option for your scenario.

 

 

3 - Should I use Task or ValueTask?

 

If you are asking yourself this question, the answer is very simple: use Task. One of the main reasons ValueTask was introduced was for reading data Streams at extremely high volumes, where operations are often not asynchronous due to buffering. If what you are building is a simple API or app that accesses values from a database, also use Task. Using ValueTask does not give you any benefit other than a small memory cost associated with Task, which is negligible, even with millions of Tasks. 

 

This post was translated from Spanish. You can see the original one here.
If there is any problem you can add a comment bellow or contact me in the website's contact form

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2025 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café