以下是按一般善意降序排列的几种解决方案:
1. default(CancellationToken)用作默认值:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
从语义上讲,CancellationToken.None它将是默认值的理想候选者,但不能这样使用,因为它不是编译时常量。default(CancellationToken)其次是最好的事情,因为它是一个编译时常量,并且正式证明与等效CancellationToken.None。
2.提供不带CancellationToken参数的方法重载:
或者,如果你在可选参数宁愿方法重载(见本和本有关该主题的问题):
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 …
}
我之所以喜欢这种解决方案,至少是因为可空类型带有较小的运行时开销,并且由于空合并运算符,对取消令牌的引用变得更加冗长??。
CancellationToken.None不仅仅是default(CancellationToken)。