Default parameter for CancellationToken

前端 未结 6 2073
猫巷女王i
猫巷女王i 2021-02-06 20:05

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 d

相关标签:
6条回答
  • 2021-02-06 20:27

    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.

    0 讨论(0)
  • 2021-02-06 20:29

    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;
        ...
    }
    
    0 讨论(0)
  • 2021-02-06 20:32

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

    Task<x> DoStuff(...., CancellationToken ct = default)
    
    0 讨论(0)
  • 2021-02-06 20:37

    Tofutim's answer is one way, but from the comments I see that people have issues with it.

    In that case, I did suggest that one can have a method as follows:

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

    and overload it as:

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

    This compiles, because the value of CancellationToken.None is not required at compile time.

    0 讨论(0)
  • 2021-02-06 20:40

    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 ??.

    0 讨论(0)
  • 2021-02-06 20:52

    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);
    }
    
    0 讨论(0)
提交回复
热议问题