我有一些异步代码要添加 CancellationToken
。但是,有许多实现不需要这样做,所以我想要一个默认参数 - 也许是 CancellationToken.None
。然而,
Task<x> DoStuff(...., CancellationToken ct = null)
产量
“
和
Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)
'ct' 的默认参数值必须是编译时常量
有没有办法为 CancellationToken
设置默认值?
new CancellationToken()
与 default
完全相同,因为 CancellationToken 是一个结构。
事实证明,以下工作:
Task<x> DoStuff(...., CancellationToken ct = default(CancellationToken))
...或者:
Task<x> DoStuff(...., CancellationToken ct = default) // C# 7.1 and later
其中 according to the documentation 的解释与 CancellationToken.None
相同:
您还可以使用 C# default(CancellationToken) 语句创建一个空的取消令牌。
有没有办法为 CancellationToken 设置默认值?
不幸的是,这是不可能的,因为 CancellationToken.None
不是编译时间常数,这是可选参数中默认值的要求。
但是,您可以通过创建重载方法而不是尝试使用默认参数来提供相同的效果:
Task<x> DoStuff(...., CancellationToken ct)
{
//...
}
Task<x> DoStuff(....)
{
return DoStuff(...., CancellationToken.None);
}
CancellationToken cancellationToken = default(CancellationToken)
怎么了?此处也有描述blogs.msdn.microsoft.com/andrewarnottms/2014/03/19/…
以下是几种解决方案,按一般优点的降序排列:
1. 使用 default(CancellationToken) 作为默认值:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
从语义上讲,CancellationToken.None
将是默认值的理想候选者,但不能这样使用,因为它不是编译时常量。 default(CancellationToken)
是次优的,因为它是编译时常量和 officially documented to be equivalent to CancellationToken.None
。
2. 提供不带 CancellationToken 参数的方法重载:
或者,如果您更喜欢方法重载而不是可选参数(请参阅关于该主题的 this 和 this 问题):
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 …
}
我最不喜欢这个解决方案,因为可空类型的运行时开销很小,并且由于空合并运算符 ??
,对取消令牌的引用变得更加冗长。
另一种选择是使用 Nullable<CancellationToken>
参数,默认为 null
,并在方法内部处理它:
Task<x> DoStuff(...., CancellationToken? ct = null) {
var token = ct ?? CancellationToken.None;
...
}
较新版本的 C# 允许默认 (CancellationToken) 版本的简化语法。例如:
Task<x> DoStuff(...., CancellationToken ct = default)
不定期副业成功案例分享
CancellationToken.None
不仅仅是default(CancellationToken)
。default(CancellationToken)
还会做什么?CancellationToken.None
将成为事实上的弃用。甚至 Microsoft 也在使用default(CancellationToken)
。例如,参见 Entity Framework 源代码中的 these search results。