.NETでは、キャッチが再スローするだけのtry / catchに利点がありますか[複製]

StackOverflow https://stackoverflow.com/questions/1207172

  •  05-07-2019
  •  | 
  •  

質問

  

可能な重複:
   C#で例外をキャッチして再スローする理由

時々、次のようなC#コードに遭遇します。

        try
        {
            // Some stuff
        }
        catch (Exception e)
        {
            throw e;
        }

例外メッセージをログに記録してから再スローするようなことができることを理解しています。例外を再スローするだけのキャッチについて話しています。これには意味がありません。 3つの質問があります:

1)これには利点がありますか

2)これによりコードが遅くなりますか

3)catchブロックが次のようであれば、違いが生じますか

        catch (Exception)
        {
            throw;
        }
役に立ちましたか?

解決

これにより、同じ例外 exact が再スローされます:

    catch (Exception)
    {
        throw;
    }

これにより、元のスタックトレースなしで例外が再スローされます。

    catch (Exception e)
    {
        throw e;
    }

例外を記録するか、例外を再スローする前に他のことを行うことができるため、 throw; の正当な理由がしばしばあります。貴重なスタックトレース情報を消去するため、 throw e; の理由はわかりません。

他のヒント

キャッチで他に何もしない場合...しかし、これは、キャッチや他の種類の例外処理など、キャッチで再スローする前に他のことを行うためによく使用されます。

このテクニックを使用して、デバッグ時にブレークポイントをスローできるようにします。終わったら削除することもあります...

主な違いは、例外のスタックトレースが変更され、最初の例のtry-catchの場所から発生したことを示すことです。

2番目の例は、スタックトレースを維持します。

利点はありますか

一般的に言えばいいえ。このパターンは、スタックトレースを新しいスローのポイントにリセットするだけです。これにより、開発者が問題の原因を突き止めるのが難しくなります

コードの速度を遅くしますか

まったく?おそらく。測定可能な差で速度を落としますか?いいえ。

catchブロックが次のようであれば、違いが生じますか?

はい、そのキャッチは本質的に完全に冗長です。元のスタックトレースを維持し、アプリケーションに目に見える影響を与えない例外を再スローします。

1-利点がまったくありません。例外を処理していない場合は、try / catchをオフのままにします。この例のもう1つの問題は、実際の例外をスローするのではなく、新しい例外をスローすることです。

2-はい-しかし、これが繰り返しコードの大きなループ内にある場合を除き、おそらく違いに気付かないでしょう。

3-はい。最初の例では、呼び出しスタックをいじっています。この例では、新しい例外をスローするのではなく、例外をバブリングしてスタックをそのまま保持します。

本当に他に何もしていない場合、私が見つけた利点は1つしかありません。 throw 行にブレークポイントを設定できます。 (例外タイプがスローされるたびに破壊するのではなく)非常に具体的になります。

しかし、デバッグ中にそれを行うだけで、その後コードを元に戻します。

違いを示す簡単なテストを作成しました。テストコードは次のとおりです。

try
{
    var broken = int.Parse("null");
}
catch (Exception ex1)
{
    System.Diagnostics.Trace.WriteLine(ex1.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception)
    {
        throw;
    }
}
catch (Exception ex2)
{
    System.Diagnostics.Trace.WriteLine(ex2.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception ex3)
    {
        throw ex3;
    }
}
catch (Exception ex4)
{
    System.Diagnostics.Trace.WriteLine(ex4.ToString());
}

これを実行すると、次の出力が得られます。

A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 18
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 33
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 49

最初の2つの例外は同じように機能します。したがって、「投げる」"スタックを上に移動する例外までは何も変更しません。ただし、「ex3を投げる」」報告された例外が異なり、例外のスタックトレースが変更されます。

これは、ロギングに適しています。また、再スローで引数を省略すると、eのスタックトレースは変更されません。

特定のタイプを介して許可したい場合があります。 FooException以外のすべての特別な処理を次に示します。

try
{
    // ...
}
catch (FooException)
{
    throw;
}
catch (Exception ex)
{
    // handle differently, like wrap with a FooException
    throw new FooException("I pitty the Foo.", ex);
}

もちろん。

ほとんどの場合、例外をスローする前にログに記録し、おそらくメソッドからいくつかの変数値を記録します。

ただキャッチして投げるだけでは、それほど多くは得られません。

そのように、いいえ。ただし、これを行うこともできます。

catch (Exception ex)
{
     LogException(ex);
     throw;
}

LogException()は、erm、例外をログに記録するか、アラートなどをメールで送信するカスタムクラスです。

重要なのは、例外のTYPEが1つだけスローされるようにすることです。それはかなり悪いアンチパターンIMHOです

e.g。

try
{
    throw XYZ();
}
catch(Exception e)
{
    throw e;
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top