一般的な善の降順でいくつかの解決策を次に示します。
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の合体演算子のために冗長になるため、私はこのソリューションが最も好きではありません??。
CancellationToken.Noneそれ以上のものになった場合、コードで何が起こるか考えてくださいdefault(CancellationToken)。