典型的なif...else
例外処理でラップされていますが、次の例のようなものはコードの重複を避けるための推奨される方法ですか?
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
throw new Exception();
}
catch(Exception ex)
{
return null;
}
の代わりに...
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
return null;
}
}
catch(Exception ex)
{
return null;
}
パフォーマンスにわずかな影響があることは知っていますが、これが許容できるプラクティスであると考えられるかどうか疑問に思っています。私は現在、2番目の方法(特に、特定の例外を異なる方法で処理する必要がある場合)を実行していますが、最初の方法が単純な場合に適しているかどうか疑問に思っていました。
フロー制御に例外処理を使用することはマイクロソフトによって推奨されていません。
そうは言っても、C#はそうすることをサポートしており、例外が最も適切な応答であるかどうかは、発生した条件に依存すると思います。
この答え で説明されているように、パフォーマンスへの影響はほとんどありません。
ですから、パフォーマンスは問題ではないという考えで進みましょう。あなたが投げているSystem.Exception
、実行をcatch
句に移動するだけです。 BadControlFlowThatShouldBeRewrittenException
を投げるのはおそらくやり過ぎでしょう。
これを分解してみましょう。我々は持っています:
GetDataFromServer
(メソッド名はC#ではPascalCaseである必要があります)。例外をスローするか、bool
を返す可能性があります。true
の場合、ProcessData
を実行します。null
を返します。このコードが書かれているメソッドは、単純に多すぎることをしているように見えます。 GetDataFromServer
を返すbool
は設計上の欠陥のように見えますが、そのメソッドがサーバーから取得しているデータを返すことを期待しています、一部IEnumerable<SomeType>
0個以上のアイテムを含む-つまり、ハッピーパスはnアイテムを返しますn> 0、not-so-happy pathは0アイテムを返し、不幸なパスは、それが何であれ、未処理の例外で爆破されます。
これにより、メソッドの外観が大きく変化します。元の投稿には1つの終了点しかないため、すべてのコードがとしてコンパイルされないため、これが意味があるかどうかを判断するのは困難です。パスは値を返すため、これは大まかな推測です。
try
{
var result = GetDataFromServer();
return ProcessData(result);
}
catch
{
return null;
}
ここでProcessData
を見て、それがresult
を繰り返していることを確認し、null
にアイテムがない場合はIEnumerable
を返します。
では、なぜメソッドがnull
を返すのですか?サーバーがダウンしていましたか?クエリにバグはありますか?接続文字列は間違った資格情報を使用していますか?予期しない例外を除いてGetDataFromServer
が爆発した場合は常に、それを飲み込み、カーペットの下に押し込んでnull
値を返します。この場合は特定の例外をキャッチし、それ以外はすべてログに記録することをお勧めします。そうすれば、デバッグがはるかに簡単になります。
例外をキャプチャしない一般的なcatch
句を使用すると、何かを診断するのがかなり難しくなります。代わりに、これを最小限に抑えます。
catch(Exception e)
{
return null;
}
これで、問題が発生した場合に少なくともe
を中断して検査できます。
TL; DR:いいえ、フロー制御の例外をスローしてキャッチすることはお勧めできません。
あなたの最初の答えには、そこにある必要のないパフォーマンスのヒットがあります。
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
throw new Exception();
}
catch(Exception ex)
{
return null;
}
いわば、コードで方向を切り替える必要がないときにifステートメントを終了してCatchステートメントに入るときです。
あなたがしたい場合は return null;
elseステートメントからスローされた後にキャッチされるcatchではなく、elseステートメントでそれを行います。
おそらくあなたのRealコードには当てはまりませんが、あなたが与えたGenericコードには当てはまります。
規格では、これを行うべきではないとしています。
標準では、このようにする必要があります(これも、OPで指定された汎用コードに基づいています)。
if (GetDataFromServer())
{
return ProcessData();
}
else
{
Return null
}
あなたがキャッチしている特定の例外がないので、ここでトライキャッチするべきではありません。
例外が発生したときにそれを確認して、例外を作成する問題を修正できるようにします。
なぜそれほど単純ではないのですか?
if (!GetDataFromServer()) return null;
ProcessData();
例外ハンドラが存在する場合は、ProcessData()にある必要があります