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


96

追加したい非同期コードがありCancellationTokenます。ただし、これが不要な実装はたくさんあるので、デフォルトのパラメータを使用したいと思いますCancellationToken.None。しかしながら、

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

収量

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

そして

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

'ct'のデフォルトのパラメーター値はコンパイル時の定数でなければなりません

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

回答:


151

次のことが機能することがわかります。

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

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

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


4
これはまさにあるフレームワークは現在ありません内部が、私は考えていない私のコードでそれを行います。マイクロソフトが実装を変更し、CancellationToken.Noneそれ以上のものになった場合、コードで何が起こるか考えてくださいdefault(CancellationToken)
noseratio

10
@Noseratioこれは後方互換性を大きく損なうので、そうなるとは思わないでしょう。そして、他に何をdefault(CancellationToken)しますか?
2014年

3
@Noseratio:あなたは厳格すぎる。おそらくCancellationToken.None実際には非推奨になるでしょう。default(CancellationToken)代わりにマイクロソフトでさえ使用しています。たとえば、Entity Frameworkのソースコードからのこれらの検索結果をご覧ください。
drowa

21
MSDNのCancellationToken.Noneプロパティから:「C#default(CancellationToken)ステートメントを使用して空のキャンセルトークンを作成することもできます」。C#の将来のバージョンがデフォルトのパラメーターとして受け入れるまで、間違いはありません。
MuiBienCarlota 2015

5
ここで 同じ2つの不足している中間の組み合わせを補うために、開発者は、cancelationTokenパラメーターにNoneまたはデフォルトのCancellationTokenを渡し、progressパラメーターにnullを渡すことができます。
Arek Bal 2015

25

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

残念ながら、これは不可能です。これはCancellationToken.None、コンパイル時定数ではないためです。これは、オプションの引数のデフォルト値の要件です。

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

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

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

6
これは、MSDN のタスクベースの非同期パターンのドキュメント(特に、提供するオーバーロードの選択のセクション)で説明されているように、これを処理する推奨方法です。
Sam Harwell 2014年

CancellationToken.None == default true
eoleary

5
どうしたのCancellationToken cancellationToken = default(CancellationToken)?また、ここで説明blogs.msdn.microsoft.com/andrewarnottms/2014/03/19/...
レイ

20

一般的な善の降順でいくつかの解決策を次に示します。

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

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

意味的にCancellationToken.Noneは、デフォルトの理想的な候補になりますが、コンパイル時の定数ではないため、そのままでは使用できません。default(CancellationToken)これはコンパイル時の定数であり、公式にと同等であると文書化されているCancellationToken.Noneため、次善の策です。

2. CancellationTokenパラメータなしでメソッドオーバーロードを提供する:

または、オプションのパラメーターよりもメソッドのオーバーロードを好む場合(このトピックに関するこの質問とこの質問を参照):

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 
}

null可能な型には実行時のオーバーヘッドがわずかにあり、キャンセルトークンへの参照がnullの合体演算子のために冗長になるため、私はこのソリューションが最も好きではありません??


11

別のオプションは、Nullable<CancellationToken>パラメータを使用し、デフォルトでにnullして、メソッド内で処理することです。

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

鮮やかさ!断然これが最良の答えです
John Henckel

4

C#の新しいバージョンでは、default(CancellationToken)バージョンの構文を簡略化できます。例えば:

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

-1

Tofutimの答えは1つの方法ですが、コメントから私は人々がそれに問題を抱えていることを理解しています。

その場合、私は次のような方法を持つことができると提案しました:

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

そしてそれを次のようにオーバーロードします:

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

の値はCancellationToken.Noneコンパイル時に必要ないため、これはコンパイルされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.