134

我有一些我想添加的异步代码CancellationToken。但是,有许多实现不需要这样做,所以我想有一个默认参数 - 也许CancellationToken.None. 然而,

Task<x> DoStuff(...., CancellationToken ct = null)

产量

“<null>”类型的值不能用作默认参数,因为没有标准转换为“System.Threading.CancellationToken”类型

Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)

'ct' 的默认参数值必须是编译时常量

有什么方法可以设置默认值CancellationToken吗?

4

5 回答 5

204

事实证明,以下工作:

Task<x> DoStuff(...., CancellationToken ct = default(CancellationToken))

...或者:

Task<x> DoStuff(...., CancellationToken ct = default) // C# 7.1 and later

根据文档,其解释与以下内容相同CancellationToken.None

您还可以使用 C#default(CancellationToken)语句创建一个空的取消标记。

于 2014-03-12T18:51:09.813 回答
26

有没有办法为 CancellationToken 设置默认值?

不幸的是,这是不可能的,因为CancellationToken.None不是编译时间常数,这是可选参数中默认值的要求。

但是,您可以通过创建重载方法而不是尝试使用默认参数来提供相同的效果:

Task<x> DoStuff(...., CancellationToken ct)
{
    //...
}

Task<x> DoStuff(....)
{
    return DoStuff(...., CancellationToken.None);
}
于 2014-03-12T17:50:23.890 回答
23

以下是几种解决方案,按一般优点的降序排列:

1. 使用default(CancellationToken)默认值:

Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }

从语义上讲,CancellationToken.None它是默认值的理想候选者,但不能这样使用,因为它不是编译时常量。default(CancellationToken)是下一个最好的东西,因为它是一个编译时常量,并且官方记录为等效于CancellationToken.None.

2.提供不带CancellationToken参数的方法重载:

或者,如果您更喜欢方法重载而不是可选参数(请参阅有关该主题的thisthis 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 …
}

我最不喜欢这个解决方案,因为可空类型的运行时开销很小,并且由于空合并运算符,对取消令牌的引用变得更加冗长??

于 2017-03-01T11:49:48.697 回答
11

另一种选择是使用Nullable<CancellationToken>参数,默认为null,并在方法内部处理:

Task<x> DoStuff(...., CancellationToken? ct = null) {
    var token = ct ?? CancellationToken.None;
    ...
}
于 2016-07-09T15:28:05.560 回答
8

较新版本的 C# 允许默认 (CancellationToken) 版本的简化语法。例如:

Task<x> DoStuff(...., CancellationToken ct = default)
于 2020-01-29T09:09:24.603 回答