Ecco diverse soluzioni, in ordine decrescente di bontà generale:
1. Utilizzo default(CancellationToken)come valore predefinito:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
Semanticamente, CancellationToken.Nonesarebbe 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 CancellationTokenparametro:
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 nullcome 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.Nonediventa qualcosa di piùdefault(CancellationToken).