CancellationTokenを追加したい非同期コードがあります。ただし、これが不要な実装が多数あるため、デフォルトのパラメーター(CancellationToken.Noneなど)が必要です。しかしながら、
Task<x> DoStuff(...., CancellationToken ct = null)
利回り
タイプ「System.Threading.CancellationToken」への標準変換がないため、タイプ ''の値をデフォルトのパラメーターとして使用できません。
そして
Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)
'ct'の既定のパラメーター値はコンパイル時の定数である必要があります
CancellationTokenにデフォルト値を設定する方法はありますか?
次のように動作することがわかりました。
_Task<x> DoStuff(...., CancellationToken ct = default(CancellationToken))
_
ドキュメントによると 、これは_CancellationToken.None
_と同じように解釈されます:
C#
default(CancellationToken)
ステートメントを使用して、空のキャンセルトークンを作成することもできます。
CancellationTokenにデフォルト値を設定する方法はありますか?
残念ながら、CancellationToken.None
はコンパイル時定数ではありません。これは、オプション引数のデフォルト値の要件です。
ただし、デフォルトのパラメーターを使用する代わりにオーバーロードされたメソッドを作成することにより、同じ効果を提供できます。
Task<x> DoStuff(...., CancellationToken ct)
{
//...
}
Task<x> DoStuff(....)
{
return DoStuff(...., CancellationToken.None);
}
一般的な利点の降順で、いくつかのソリューションを次に示します。
default(CancellationToken)
をデフォルト値として使用:_Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
_
意味的には、_CancellationToken.None
_はデフォルトの理想的な候補ですが、コンパイル時の定数ではないため、そのように使用することはできません。 default(CancellationToken)
は、コンパイル時の定数であり、 公式には_CancellationToken.None
_ と同等であると文書化されているため、次善の策です。
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);
}
_
これにより、インターフェイスがスリムになり、実装者が転送方法のオーバーロードを明示的に記述する必要がなくなります。
null
をデフォルト値として使用します。_Task DoAsync(…, CancellationToken? ct = null)
{
… ct ?? CancellationToken.None …
}
_
Nullable型には実行時のオーバーヘッドがわずかにあり、null合体演算子_??
_によりキャンセルトークンへの参照がより冗長になるため、このソリューションが最も好きではありません。
別のオプションは、Nullable<CancellationToken>
パラメータ、デフォルトはnull
であり、メソッド内で処理します。
Task<x> DoStuff(...., CancellationToken? ct = null) {
var token = ct ?? CancellationToken.None;
...
}