Task.FromResult può restituire il singleton

Task.FromResult<TResult>(TResult) può ora restituire un'istanza memorizzata nella cache Task<TResult> anziché creare sempre una nuova istanza.

Comportamento precedente

Nelle versioni precedenti, Task.FromResult<TResult>(TResult) alloca sempre un nuovo Task<TResult>, indipendentemente dal tipo di T o dal valore del risultato.

Nuovo comportamento

Per alcuni tipi di T e alcuni valori dei risultati, Task.FromResult<TResult>(TResult) può restituire un oggetto singleton memorizzato nella cache anziché allocare un nuovo oggetto. Ad esempio, è probabile che ogni chiamata a Task.FromResult(true) restituisca lo stesso oggetto già completato Task<bool>.

Versione introdotta

.NET 6

Tipo di modifica che causa un'interruzione

Questa modifica può influire sulla compatibilità binaria.

Motivo della modifica

Molti sviluppatori si aspettavano che Task.FromResult<TResult>(TResult) si comportasse in modo analogo ai metodi asincroni, che già hanno eseguito tale memorizzazione nella cache. Gli sviluppatori che sapevano del comportamento di allocazione spesso mantenevano la propria cache per evitare il costo delle prestazioni di allocazione continua per questi valori di uso comune. Ad esempio:

private static readonly Task<bool> s_trueTask = Task.FromResult(true);

Ora, tali cache personalizzate non sono più necessarie per valori come Boolean e valori Int32 piccoli.

A meno che non si stia usando l'uguaglianza dei riferimenti per verificare se un'istanza di Task è uguale a un'altra istanza di Task, l’utente non dovrebbe essere interessato da questa modifica. Se si usa tale uguaglianza di riferimento ed è necessario continuare questo controllo, utilizzare il codice seguente per assicurarsi che venga sempre restituita un'istanza Task<TResult> univoca:

private static Task<T> NewInstanceFromResult<T>(T result)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.TrySetResult(result);
    return tcs.Task;
}

Nota

Questo modello è molto meno efficiente rispetto all'uso di Task.FromResult(result) e deve essere evitato a meno che non sia effettivamente necessario.

API interessate