web-dev-qa-db-ja.com

CancellationTokenのデフォルトパラメータ

CancellationTokenを追加したい非同期コードがあります。ただし、これが不要な実装が多数あるため、デフォルトのパラメーター(CancellationToken.Noneなど)が必要です。しかしながら、

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

利回り

タイプ「System.Threading.CancellationToken」への標準変換がないため、タイプ ''の値をデフォルトのパラメーターとして使用できません。

そして

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

'ct'の既定のパラメーター値はコンパイル時の定数である必要があります

CancellationTokenにデフォルト値を設定する方法はありますか?

71
tofutim

次のように動作することがわかりました。

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

ドキュメントによると 、これは_CancellationToken.None_と同じように解釈されます:

C#default(CancellationToken)ステートメントを使用して、空のキャンセルトークンを作成することもできます。

107
tofutim

CancellationTokenにデフォルト値を設定する方法はありますか?

残念ながら、CancellationToken.Noneはコンパイル時定数ではありません。これは、オプション引数のデフォルト値の要件です。

ただし、デフォルトのパラメーターを使用する代わりにオーバーロードされたメソッドを作成することにより、同じ効果を提供できます。

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

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

一般的な利点の降順で、いくつかのソリューションを次に示します。

1. default(CancellationToken)をデフォルト値として使用:

_Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
_

意味的には、_CancellationToken.None_はデフォルトの理想的な候補ですが、コンパイル時の定数ではないため、そのように使用することはできません。 default(CancellationToken)は、コンパイル時の定数であり、 公式には_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型には実行時のオーバーヘッドがわずかにあり、null合体演算子_??_によりキャンセルトークンへの参照がより冗長になるため、このソリューションが最も好きではありません。

18
stakx

別のオプションは、Nullable<CancellationToken>パラメータ、デフォルトはnullであり、メソッド内で処理します。

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