21

C# では、'Catch'、'Catch (Exception)'、および 'Catch(Exception e)' の違いは何ですか?

try-catch に関する MSDNの記事では、例で 2 つを使用していますが、使用目的の違いについては説明していません。

try
{}
catch 
{}

try 
{}
catch (Exception)
{}

try
{}
catch(Exception e)
{}

これらはどう違うのですか?すべての例外をキャッチするのはどれで、特定の例外をキャッチするのはどれですか?

4

7 に答える 7

46

この問題の歴史的側面について言及した人はまだ誰もいません。

.NET では、 から派生していないオブジェクトをスローすることは合法Exceptionです。(C# では合法ではありませんが、他のマネージ言語では合法です。) 多くの人はこの事実を認識していませんが、合法です。それはクレイジーなので、.NET 2.0 ではデフォルトが変更されました。例外ではないものをスローしようとすると、明らかに例外であるクラスに自動的にラップさRuntimeWrappedExceptionます。その後、そのオブジェクトがスローされます。

この奇妙さのために、C# 1.0 では、両方を実行するコードがよく見られました。

try
{ do something }
catch(Exception) 
{ handle the exception }
catch
{ handle the thrown non-exception }

実際、セキュリティと正確性の問題がありました。セキュリティ上の理由から、スローされたものをすべてキャッチする必要があり(おそらく再スローするために)、人々はそれcatch(Exception)がすべてをキャッチしたと合理的に考えますが、そうではありませんでした。

幸いなことに、.NET 2.0 以降はより合理的になりました。に頼ることができcatch {}、必要catch(Exception) {}catch(Exception ex) {}応じてすべてをキャッチできます。

そして最後に: なんらかの理由で C# 1.0 の動作を有効にしたい場合は、

[assembly:System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = false)]

あなたのプログラムで。

于 2013-06-12T19:51:00.610 に答える
24

要するに...

Catchパラメータを指定しないと例外が発生しますが、それに対処する手段はありません。

Catch (Exception)Exceptionルートタイプを指定したため、基本的に同じことを行います。Catch (IOException)タイプのみをキャッチするのとは対照的にIOException

Catch (Exception ex)すべての例外をキャッチし、ex変数を介してそれに対処する手段を提供します。

詳細: http://msdn.microsoft.com/en-us/library/ms173160.aspx

于 2013-06-12T19:41:10.493 に答える
9

最初のバージョンは、Exception クラスから派生したすべての例外をキャッチします。

2 番目のバージョンは、指定された例外をキャッチします。

3 番目のバージョンは、宣言された名前で指定された例外をキャッチします。次に、catch ブロックでこのオブジェクトを使用して、たとえば、完全なエラーを表示できます。e.ToString();

詳細はこちらをご覧ください

于 2013-06-12T19:39:09.570 に答える
6

それらはすべて基本的に同じことを行いますが、エラーに関して提供される情報の量が異なります。

catch (foo ex) {}type にキャストできるものを除いて、すべての例外を除外しますfoo。また、作業するエラーのインスタンスも提供されます。

catch (foo) {}上記と同じことを行いますが、例外のインスタンスは提供しません。例外の種類はわかりますが、そこから情報を読み取ることはできません。

どちらの場合でも、例外のタイプが の場合、Exceptionすべての例外がキャッチされることに注意してください。

catch {}すべての例外をキャッチします。キャッチされたタイプがわからず、インスタンスにアクセスできません。

例外がキャッチされた場合に必要な情報量に基づいて、どちらを使用するかを選択できます。

どちらを使用するかに関係なく、コマンドを使用してthrow;(引数なしで) キャッチされた例外を前方に渡すことができます。

于 2013-06-12T19:43:59.343 に答える
3

あなたの例では、例外で何もしていないので、何もしません。しかし、明確にするために…

  • これはすべてをキャッチしますが、例外は何もしません。

    catch {}
    

    これは、メソッドからの戻りを保証したい場合にのみ役立ちます。

  • Exceptionこれは、タイプの例外(すべて)のみをキャッチしますが、例外に対しては何もしません。

    catch (Exception) {}
    

    これは、処理するタイプを指定して、キャッチする例外のタイプを制限したい場合に便利です。その他の例外は、適切なハンドラーが見つかるまでコール スタックをバブルアップします。

  • これは、タイプの例外のみをキャッチしException(これがすべてです)、例外で何かを行うことができますが、たまたま何もしません

    catch (Exception ex) {}
    

    この手法により、より多くのオプションが提供されます。例外をログに記録したり、を検査したりInnerExceptionできます。また、処理する例外の種類を指定できます。

何らかの方法で例外を再スローしない限り、これらはすべて悪い習慣です。一般に、有意義に処理できる例外のみをキャッチし、それ以外はすべてバブルアップできるようにする必要があります。

于 2013-06-12T19:41:04.533 に答える
1

catch(Exception e) を追加すると、Message や StackTrace など、スローされた例外に関する詳細を含む Exception オブジェクトにアクセスできるようになります。この情報をログに記録すると、バグの診断に役立ちます。キャッチしようとしている例外を宣言しない単純なキャッチでは、例外オブジェクトにアクセスできません。

また、基本的な Exception をキャッチすることは一般的すぎるため、一般的に悪い習慣と見なされます。たとえば、ファイルを操作している場合は、次の try/catch ブロックを検討できます。

try{
    //open your file and read/write from it here
}catch(FileNotFoundException fe){
    //log the message
    Log(fe.Message);
}catch(Exception e){
    //you can catch a general exception at the end if you must
}finally{
    //close your file
}
于 2013-06-12T19:50:11.750 に答える