非同期メソッドを実装されていない/サポートされていない、または無効な操作としてマークする正しい方法は何ですか。簡単にするために、私は使用しますNotImplementedException
例では、しかし質問はに適用されますNotSupportedException
そしてInvalidOperationException
同様に。
同期的には、単純に例外を投げるでしょう:
public override void X() {
throw new NotImplementedException();
}
非同期の世界では、このコードに相当するものは何でしょうか。
/* 1 */ public override Task XAsync() {
throw new NotImplementedException();
}
または
/* 2 */ public override Task XAsync() {
return Task.FromException(new NotImplementedException());
}
これらのアプローチの複雑さは何ですか?もっと良い方法はありますか?
「いや、ここで非同期になるメソッドは必要ありません」/「非同期ではありません」このメソッドは何らかのインタフェースまたは抽象クラスを実装していると言えます。
私が考えていないいくつかの方法:
/* 3 */ public async override Task XAsync() { // here is an CS1998 warning
throw new NotImplementedException();
}
コンパイラ無駄なステートマシンを生成するだけですこれは意味的に2と同等です
/* 4 */ public async override Task XAsync() {
await Task.Yield();
throw new NotImplementedException();
}
これは同じ3と同じですが、Task.Yeild()を待ちます。
を返すメソッドを呼び出すときTask
その一部は同期的に実行されます(実装メソッドが次のように定義されていても)。async
そして持っていますawait
それを呼び出します。最初の時点まで、デフォルトではすべて同期です。
そのため、結果はすべてのオプションで同じです。すぐにスローするか、既に例外が発生して完了しているタスクを返す(すぐに呼び出しを待っている場合にのみ同じ動作をする)またはメソッドをマークするasync
(これはあなたがawait
呼び出しますが、完全を期すために追加しましょう。
私はすぐに投げに行きますタスクを返すことはあなたが「仕事を始めた」ことを示すかもしれないからです。呼び出し側はタスクを待つ必要はありませんそのため、発信者がいつあなたのTask
メソッドが実装されていないという事実は表示されません。
async
キーワード。 - Martin Ullrich
私は四肢に出かけて「それは関係ない」と言うつもりです。
骨頭の例外直接投げることができます(throw
)または返されたタスクに配置(Task.FromException
)それらは骨頭の例外なので、とにかく捕らえられるべきではありません、それでそれらがどこに投げられるかは問題ではありません。
あなたのコメントでは、あなたは書いた:
NHibernateの非同期版を作ろうとしています:)
それはあなたを不幸な立場にします。熟練したプログラマーによって書かれた有名なライブラリは熟練していないプログラマーによる偶然の誤用(コピー/ペーストによる誤用を含む)から保護するためによく書かれているべきです。
次のようなコードを期待する十分な人がいますawait Task.WhenAll(a(), b(), c())
非同期操作の1つが失敗しても動作するように、私はあなたの最初の選択肢は選択肢にすべきではないと言うでしょう。もしb()
同期的に例外を投げますa()
から返されたタスクは無視されます。c()
呼び出されません。
私はスティーブンクリーリーの答えに同意しますNotImplementedException
彼が言っているように、とにかくプロダクションコードになることは決してないので、それは問題ではないところで骨頭の例外です。しかし、あなたは書きます:
質問はに適用されます
NotSupportedException
そしてInvalidOperationException
同様に。
これらは必ずしも骨頭の例外ではありません。これらできた製品コードになってしまいます。
あなたの2番目の選択肢はその問題を回避します。
あなたの2番目のオプションには追加の問題があります。実際には例外はスローされないので、デバッグを妨げています。何か問題が発生した場合は、デバッガに例外が発生した時点でブレークするオプションを用意すると非常に便利です。投げられる場所ではなく捕まった。
私も検討を提案した
public async override Task XAsync() {
throw new NotImplementedException();
}
ステートマシンの作成に関連するオーバーヘッドがあるため、これは破棄しました。これはそれを破棄する正当な理由ではないと思います。これはパフォーマンスに関係のないコードです。これはエラーの場合のみを処理するコードです。私はそれを提案したasync
/await
なぜなら、開発時間の節約になるほど時間がかかるからです。
私はあなたがなぜこのオプションを使いたくないのか理解していますが、私は個人的にはまだそうしています。それはあなたの最初の選択肢の欠点を回避します。それはあなたの2番目の選択肢の欠点を回避します。それ自体の欠点、わずかに遅いパフォーマンスは、私の経験では他の2つよりも問題になる可能性が低いです。
他の2つのうち、うまくいけば欠点の詳細はあなたが十分に情報に基づいた決定を下すのを助ける。
async Task XAsync() { throw ...; }
別の選択肢です。とともにasync
キーワード。 - user743382