Ecco diverse soluzioni, in ordine decrescente di bontà generale:
1. Utilizzo default(CancellationToken)
come valore predefinito:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
Semanticamente, CancellationToken.None
sarebbe il candidato ideale per l'impostazione predefinita, ma non può essere utilizzato come tale perché non è una costante del tempo di compilazione. default(CancellationToken)
è la prossima cosa migliore perché è una costante del tempo di compilazione e ufficialmente documentata per essere equivalente aCancellationToken.None
.
2. Fornire un sovraccarico del metodo senza un CancellationToken
parametro:
Oppure, se preferisci gli overload del metodo rispetto ai parametri opzionali (vedi questa e questa domanda su quell'argomento):
Task DoAsync(CancellationToken ct) { … } // actual method always requires a token
Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token
Per i metodi di interfaccia, lo stesso può essere ottenuto utilizzando metodi di estensione:
interface IFoo
{
Task DoAsync(CancellationToken ct);
}
static class Foo
{
public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None);
}
Ciò si traduce in un'interfaccia più snella e si evita agli implementatori di scrivere esplicitamente il sovraccarico del metodo di inoltro.
3. Rendendo il parametro nullable e utilizzando null
come valore predefinito:
Task DoAsync(…, CancellationToken? ct = null)
{
… ct ?? CancellationToken.None …
}
Mi piace questa soluzione almeno perché i tipi nullable hanno un piccolo overhead di runtime ei riferimenti al token di annullamento diventano più dettagliati a causa dell'operatore di coalescenza null ??
.
CancellationToken.None
diventa qualcosa di piùdefault(CancellationToken)
.