C#でtry~catchを行うとき、catchブロックでthrowのみ書いてるソースがあったので
意味あんのか?ってことで調べてみた。
自分の認識では関数内のExceptionは最終的に.Net Frameworkが受けてくれるので
単にthrowするだけなら意味がないように思う。
ということで、スタックトレースがどう違うかを比べてみた。
①Hoge1~3はtry~catchを行わず、呼び出し元でtry~catchしてみる。
#region Hoge
private void button1_Click(object sender, EventArgs e)
{
try
{
Hoge();
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("********Hoge*********");
Console.WriteLine(ex.ToString());
}
}
private void Hoge()
{
Hoge1();
}
private void Hoge1()
{
Hoge2();
}
private void Hoge2()
{
Hoge3();
}
private void Hoge3()
{
throw new DivideByZeroException();
}
#endregion
②Foo1~3はtry~catchを行ない、catch句ではthrow;のみする
#region Foo
private void button2_Click(object sender, EventArgs e)
{
try
{
Foo();
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("********Foo*********");
Console.WriteLine(ex.ToString());
}
}
private void Foo()
{
try
{
Foo1();
}
catch
{
throw;
}
}
private void Foo1()
{
try
{
Foo2();
}
catch
{
throw;
}
}
private void Foo2()
{
try
{
Foo3();
}
catch
{
throw;
}
}
private void Foo3()
{
throw new DivideByZeroException();
}
#endregion
③Func1~3はtry~catchを行ない、catch句ではthrowされたExceptionをさらにthrowする
#region Func
private void button3_Click(object sender, EventArgs e)
{
try
{
Func();
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("********Func*********");
Console.WriteLine(ex.ToString());
}
}
private void Func()
{
try
{
Func1();
}
catch (DivideByZeroException ex)
{
throw ex;
}
}
private void Func1()
{
try
{
Func2();
}
catch (DivideByZeroException ex)
{
throw ex;
}
}
private void Func2()
{
try
{
Func3();
}
catch(DivideByZeroException ex)
{
throw ex;
}
}
private void Func3()
{
throw new DivideByZeroException();
}
#endregion
①結果
********Hoge*********
System.DivideByZeroException: 0 で除算しようとしました。
場所 WindowsFormsApplication1.Form1.Hoge3() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 53
場所 WindowsFormsApplication1.Form1.Hoge2() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 48
場所 WindowsFormsApplication1.Form1.Hoge1() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 43
場所 WindowsFormsApplication1.Form1.Hoge() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 37
場所 WindowsFormsApplication1.Form1.button1_Click(Object sender, EventArgs e) 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 25
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
②結果
********Foo*********
System.DivideByZeroException: 0 で除算しようとしました。
場所 WindowsFormsApplication1.Form1.Foo3() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 110
場所 WindowsFormsApplication1.Form1.Foo2() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 104
場所 WindowsFormsApplication1.Form1.Foo1() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 92
場所 WindowsFormsApplication1.Form1.Foo() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 80
場所 WindowsFormsApplication1.Form1.button2_Click(Object sender, EventArgs e) 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 62
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
例外がスローされました: 'System.DivideByZeroException' (WindowsFormsApplication1.exe の中)
③結果
********Func*********
System.DivideByZeroException: 0 で除算しようとしました。
場所 WindowsFormsApplication1.Form1.Func() 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 137
場所 WindowsFormsApplication1.Form1.button3_Click(Object sender, EventArgs e) 場所 D:\94_DevelopVS\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 119
■結論
ということで、 catch句で何かしらの処理を行うならアリだが、単にthrow;だけなら不要。
③のパターンはスタックトレースが最後のthrow分しか残ってないので最悪。
普通に①でやるのがよさげ。