我有时会遇到如下所示的C#代码:
try
{
// Some stuff
}
catch (Exception e)
{
throw e;
}
我理解可以做一些事情,比如记录异常消息然后重新抛出它。我在谈论只能重新抛出异常的问题。我没有看到这一点。我有三个问题:
1)这个
有什么好处2)这样做是否会慢慢编写代码
3)如果catch块如下,它会有什么不同:
catch (Exception)
{
throw;
}
答案 0 :(得分:20)
这会重新抛出完全相同的异常:
catch (Exception)
{
throw;
}
虽然这会在没有原始堆栈跟踪的情况下重新抛出异常:
catch (Exception e)
{
throw e;
}
throw;
通常有充分的理由,因为您可以在重新抛出异常之前记录异常或执行其他操作。我不知道throw e;
有什么好的理由,因为你会消除有价值的堆栈跟踪信息。
答案 1 :(得分:3)
如果你在catch中没有做任何其他事情,那就不行了......但是在重新抛出之前,这常常用于捕获其他内容,例如日志记录或其他类型的异常处理。
答案 2 :(得分:2)
我使用这种技术,所以我可以在调试时在throw上放置一个断点。有时我在完成后删除它......
答案 3 :(得分:2)
主要区别在于异常的堆栈跟踪将被更改,以显示它来自第一个示例中try-catch的位置。
第二个示例维护堆栈跟踪。
答案 4 :(得分:2)
一般来说没有。所有这种模式都会将堆栈跟踪重置为新抛出的点。这将使开发人员更难以追踪问题的根源
一点都没有?有可能。减慢任何可衡量的差异?没有。
是的,这种捕获基本上是完全多余的。它将重新抛出异常,这将保留原始堆栈跟踪并且对您的应用程序没有可疑的影响。
答案 5 :(得分:1)
1 - 我看不到任何优势。如果您没有处理异常,请关闭try / catch。这个例子的另一个问题是你没有抛出实际的异常,而是抛出一个新异常。
2 - 是的 - 但除非这是一个重复代码的大循环,否则你可能不会注意到差异。
3 - 是的。在第一个示例中,您正在搞乱调用堆栈。这个例子通过冒泡异常来保持堆栈的完整性,而不是抛出新的异常。
答案 6 :(得分:1)
如果你真的没有做任何其他事情,那么我找到的只有一个优势:你可以在throw
线上设置一个断点。它使它非常具体(而不是在抛出异常类型时断开)。
我只会在调试时执行此操作,然后将代码还原。
答案 7 :(得分:1)
这对记录来说通常很好。此外,如果你在重新抛出中省去参数,那么它不会改变e的堆栈跟踪。
有时您希望允许通过某些类型,例如除了FooException之外,这里有一些特殊处理:
try
{
// ...
}
catch (FooException)
{
throw;
}
catch (Exception ex)
{
// handle differently, like wrap with a FooException
throw new FooException("I pitty the Foo.", ex);
}
答案 8 :(得分:1)
我写了一个快速测试来显示差异。这是测试代码:
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
您会注意到前两个例外工作方式相同。所以,“扔;”对于向上移动堆栈的异常,它不会改变任何东西。然而“扔ex3;”导致报告的异常不同,更改异常的堆栈跟踪。
答案 9 :(得分:0)
不确定
大多数情况下,您希望在抛出异常之前记录异常,并且可能会从方法中记录一些变量值。
然而,抓住它扔掉它并不能让你获得很多。答案 10 :(得分:0)
就像那样,没有。但是,您可能希望这样做:
catch (Exception ex)
{
LogException(ex);
throw;
}
其中LogException()是一个自定义类,它会记录异常或通过电子邮件发送警报或其他内容。
答案 11 :(得分:-1)
我认为重点是确保只抛出一种TYPE异常。这是一个非常糟糕的反模式恕我直言
e.g。
try
{
throw XYZ();
}
catch(Exception e)
{
throw e;
}