Aquí hay varias soluciones, en orden descendente de bondad general:
1. Usando default(CancellationToken)
como valor predeterminado:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
Semánticamente, CancellationToken.None
sería el candidato ideal para el valor predeterminado, pero no se puede usar como tal porque no es una constante en tiempo de compilación. default(CancellationToken)
es la mejor opción porque es una constante en tiempo de compilación y está oficialmente documentada como equivalente aCancellationToken.None
.
2. Proporcionar una sobrecarga de método sin un CancellationToken
parámetro:
O, si prefiere las sobrecargas de métodos sobre los parámetros opcionales (consulte esta y esta pregunta sobre ese tema):
Task DoAsync(CancellationToken ct) { … } // actual method always requires a token
Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token
Para los métodos de interfaz, se puede lograr lo mismo utilizando métodos de extensión:
interface IFoo
{
Task DoAsync(CancellationToken ct);
}
static class Foo
{
public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None);
}
Esto da como resultado una interfaz más delgada y evita que los implementadores escriban explícitamente la sobrecarga del método de reenvío.
3. Hacer que el parámetro sea anulable y usar null
como valor predeterminado:
Task DoAsync(…, CancellationToken? ct = null)
{
… ct ?? CancellationToken.None …
}
Me gusta esta solución menos porque los tipos que aceptan valores NULL vienen con una pequeña sobrecarga de tiempo de ejecución, y las referencias al token de cancelación se vuelven más detalladas debido al operador de fusión nulo ??
.
CancellationToken.None
convierte en algo más quedefault(CancellationToken)
.