Aqui estão várias soluções, em ordem decrescente de bondade geral:
1. Usando default(CancellationToken)
como valor padrão:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
Semanticamente, CancellationToken.None
seria o candidato ideal para o padrão, mas não pode ser usado como tal porque não é uma constante de tempo de compilação. default(CancellationToken)
é a próxima melhor coisa porque é uma constante de tempo de compilação e oficialmente documentada para ser equivalente aCancellationToken.None
.
2. Fornecer uma sobrecarga de método sem um CancellationToken
parâmetro:
Ou, se você preferir sobrecargas de método em vez de parâmetros opcionais (consulte esta e esta pergunta sobre esse tópico):
Task DoAsync(CancellationToken ct) { … } // actual method always requires a token
Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token
Para métodos de interface, o mesmo pode ser alcançado usando métodos de extensão:
interface IFoo
{
Task DoAsync(CancellationToken ct);
}
static class Foo
{
public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None);
}
Isso resulta em uma interface mais estreita e evita que os implementadores gravem explicitamente a sobrecarga do método de encaminhamento.
3. Tornando o parâmetro anulável e usando null
como valor padrão:
Task DoAsync(…, CancellationToken? ct = null)
{
… ct ?? CancellationToken.None …
}
Gosto menos dessa solução porque os tipos anuláveis vêm com uma pequena sobrecarga de tempo de execução e as referências ao token de cancelamento se tornam mais detalhadas por causa do operador de coalescência nulo ??
.
CancellationToken.None
se tornar algo maisdefault(CancellationToken)
.