CancellationToken的默认参数

时间:2014-03-12 17:45:53

标签: c# asynchronous task-parallel-library cancellation-token

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

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

产量

  

类型&#39;&#39;的值不能用作默认参数,因为   没有标准的转换类型   &#39; System.Threading.CancellationToken&#39;

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

&#39; ct&#39;的默认参数值必须是编译时常量

是否有任何方法可以为CancellationToken设置默认值?

6 个答案:

答案 0 :(得分:101)

事实证明以下工作:

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

according to the documentation,其解释与CancellationToken.None相同:

  

您还可以使用C#default(CancellationToken)语句进行创建   一个空的取消令牌。

答案 1 :(得分:21)

  

是否有任何方法可以为CancellationToken设置默认值?

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

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

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

Task<x> DoStuff(....)
{
    return DoStuff(...., CancellationToken.None);
}

答案 2 :(得分:16)

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

1。使用default(CancellationToken)作为默认值:

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

从语义上讲,CancellationToken.None将是默认的理想候选者,但不能这样使用,因为它不是编译时常量。 default(CancellationToken)是下一个最好的东西,因为它是一个编译时常量officially documented to be equivalent to CancellationToken.None

2。提供没有CancellationToken参数的方法重载:

或者,如果您更喜欢方法重载而不是可选参数(请参阅该主题的thisthis问题):

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 …
}

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

答案 3 :(得分:10)

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

null

答案 4 :(得分:7)

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

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

答案 5 :(得分:-1)

Tofutim's answer是一种方式,但从评论中我发现人们对此有疑问。

在这种情况下,我确实建议可以采用如下方法:

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

并将其重载为:

Task<x> DoStuff(....)
{
    return DoStuff(...., CancellationToken.None);
}

这会编译,因为在编译时不需要CancellationToken.None的值。