12

非同期メソッドを実装されていない/サポートされていない、または無効な操作としてマークする正しい方法は何ですか。簡単にするために、私は使用します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()を待ちます。


  • 良い質問。最初のオプションは、メソッドが呼び出されたときに例外をスローし、2番目の結果は結果が待っているときにスローします。最初の選択肢は「早期に失敗する」ので少し好みがありますが、専門家の言うことには興味がありません。 - Heinzi
  • 多分それは役立ちます:stackoverflow.com/a/13254787/316799 - Felipe Oriani
  • ええ、@ FelipeOrianiはそれを見ました、ありがとう - hazzik
  • "あなたがカバーしようとしている正確なシナリオを明確にしない限り" NHibernateの非同期版を作ろうとしています:)github.com/nhibernate/nhibernate-core/pull/588 - hazzik
  • @ hazzikはい。私のコメントを理解できませんでしたか?私が言っているasync Task XAsync() { throw ...; }別の選択肢です。とともにasyncキーワード。 - user743382

3 답변


3

を返すメソッドを呼び出すときTaskその一部は同期的に実行されます(実装メソッドが次のように定義されていても)。asyncそして持っていますawaitそれを呼び出します。最初の時点まで、デフォルトではすべて同期です。

そのため、結果はすべてのオプションで同じです。すぐにスローするか、既に例外が発生して完了しているタスクを返す(すぐに呼び出しを待っている場合にのみ同じ動作をする)またはメソッドをマークするasync(これはあなたがawait呼び出しますが、完全を期すために追加しましょう。

私はすぐに投げに行きますタスクを返すことはあなたが「仕事を始めた」ことを示すかもしれないからです。呼び出し側はタスクを待つ必要はありませんそのため、発信者がいつあなたのTaskメソッドが実装されていないという事実は表示されません。


  • 私はこれを志向していますが... bcを構築することができませんでした' - micahhoover
  • タスクを返すメソッドをスローするだけの場合は、メソッドを使用してメソッドを定義しないでください。asyncキーワード。 - Martin Ullrich

4

私は四肢に出かけて「それは関係ない」と言うつもりです。

骨頭の例外直接投げることができます(throw)または返されたタスクに配置(Task.FromException)それらは骨頭の例外なので、とにかく捕らえられるべきではありません、それでそれらがどこに投げられるかは問題ではありません。


2

あなたのコメントでは、あなたは書いた:

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つのうち、うまくいけば欠点の詳細はあなたが十分に情報に基づいた決定を下すのを助ける。

リンクされた質問


関連する質問

最近の質問