以下是几种解决方案,按一般优点的降序排列:
1. 使用default(CancellationToken)
默认值:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
从语义上讲,CancellationToken.None
它是默认值的理想候选者,但不能这样使用,因为它不是编译时常量。default(CancellationToken)
是下一个最好的东西,因为它是一个编译时常量,并且官方记录为等效于CancellationToken.None
.
2.提供不带CancellationToken
参数的方法重载:
或者,如果您更喜欢方法重载而不是可选参数(请参阅有关该主题的this和this question):
Task DoAsync(CancellationToken ct) { … } // actual method always requires a token
Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token
对于接口方法,同样可以使用扩展方法来实现:
interface IFoo
{
Task DoAsync(CancellationToken ct);
}
static class Foo
{
public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None);
}
这导致了更精简的接口,并使实现者无需显式编写转发方法重载。
3. 使参数可以为空并null
用作默认值:
Task DoAsync(…, CancellationToken? ct = null)
{
… ct ?? CancellationToken.None …
}
我最不喜欢这个解决方案,因为可空类型的运行时开销很小,并且由于空合并运算符,对取消令牌的引用变得更加冗长??
。