Default parameter for CancellationToken

C#AsynchronousTask Parallel-LibraryCancellation Token

C# Problem Overview


I have some async code that I would like to add a CancellationToken to. However, there are many implementations where this is not needed so I would like to have a default parameter - perhaps CancellationToken.None. However,

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

yields

> A value of type '<null>' cannot be used as a default parameter because > there are no standard conversions to type > 'System.Threading.CancellationToken'

and

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

> Default parameter value for 'ct' must be a compile-time constant

Is there any way to have a default value for CancellationToken?

C# Solutions


Solution 1 - C#

It turns out that the following works:

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

...or:

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

which, according to the documentation, is interpreted the same as CancellationToken.None:

> You can also use the C# default(CancellationToken) statement to create > an empty cancellation token.

Solution 2 - C#

> Is there any way to have a default value for CancellationToken?

Unfortunately, this is not possible, as CancellationToken.None is not a compile time constant, which is a requirement for default values in optional arguments.

You can provide the same effect, however, by making an overloaded method instead of trying to use default parameters:

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

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

Solution 3 - C#

Here are several solutions, in descending order of general goodness:

1. Using default(CancellationToken) as default value:
Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }

Semantically, CancellationToken.None would be the ideal candidate for the default, but cannot be used as such because it isn't a compile-time constant. default(CancellationToken) is the next best thing because it is a compile-time constant and officially documented to be equivalent to CancellationToken.None.

2. Providing a method overload without a CancellationToken parameter:

Or, if you prefer method overloads over optional parameters (see this and this question on that topic):

Task DoAsync(CancellationToken ct) { … } // actual method always requires a token
Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token

For interface methods, the same can be achieved using extension methods:

interface IFoo
{
    Task DoAsync(CancellationToken ct);
}

static class Foo
{
    public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None);
}

This results in a slimmer interface and spares implementers from explicitly writing the forwarding method overload.

3. Making the parameter nullable and using null as default value:
Task DoAsync(…, CancellationToken? ct = null)
{
    … ct ?? CancellationToken.None …
}

I like this solution least because nullable types come with a small runtime overhead, and references to the cancellation token become more verbose because of the null coalescing operator ??.

Solution 4 - C#

Another option is to use a Nullable<CancellationToken> parameter, default it to null, and deal with it inside the method:

Task<x> DoStuff(...., CancellationToken? ct = null) {
    var token = ct ?? CancellationToken.None;
    ...
}

Solution 5 - C#

Newer versions of C# allow for a simplified syntax for the default(CancellationToken) version. E.g.:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontofutimView Question on Stackoverflow
Solution 1 - C#tofutimView Answer on Stackoverflow
Solution 2 - C#Reed CopseyView Answer on Stackoverflow
Solution 3 - C#stakx - no longer contributingView Answer on Stackoverflow
Solution 4 - C#Todd MenierView Answer on Stackoverflow
Solution 5 - C#Alexei - check CodidactView Answer on Stackoverflow