在.NET中,try / catch是否有任何优势,其中catch只是重新抛出[duplicate]

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

  •  05-07-2019
  •  | 
  •  

  

可能重复:
  为什么要在C#中捕获并重新抛出异常?

我有时会遇到如下所示的C#代码:

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

我理解可以做一些事情,比如记录异常消息然后重新抛出它。我在谈论只能重新抛出异常的问题。我没有看到这一点。我有三个问题:

1)这个

有什么好处

2)这样做是否会慢慢编写代码

3)如果catch块如下,它会有什么不同:

        catch (Exception)
        {
            throw;
        }
有帮助吗?

解决方案

这会重新抛出完全相同的异常:

    catch (Exception)
    {
        throw;
    }

虽然这会在没有原始堆栈跟踪的情况下重新抛出异常:

    catch (Exception e)
    {
        throw e;
    }

throw; 通常有充分的理由,因为您可以在重新抛出异常之前记录异常或执行其他操作。我不知道 throw e; 有什么好的理由,因为你会消除有价值的堆栈跟踪信息。

其他提示

如果你在catch中没有做任何其他事情,那就不行了......但是在重新抛出之前,这常常用于捕获其他内容,例如日志记录或其他类型的异常处理。

我使用这种技术,所以我可以在调试时在throw上放置一个断点。有时我在完成后删除它......

主要区别在于异常的堆栈跟踪将被更改,以显示它来自第一个示例中try-catch的位置。

第二个示例维护堆栈跟踪。

是否有优势

一般来说没有。所有这种模式都会将堆栈跟踪重置为新抛出的点。这将使开发人员更难以追踪问题的根源

它是否会减慢代码

一点都没有?有可能。减慢任何可衡量的差异?没有。

如果catch块如下,它会有什么不同吗?

是的,这种捕获基本上是完全多余的。它将重新抛出异常,这将保留原始堆栈跟踪并且对您的应用程序没有可疑的影响。

1 - 我看不到任何优势。如果您没有处理异常,请关闭try / catch。这个例子的另一个问题是你没有抛出实际的异常,而是抛出一个新异常。

2 - 是的 - 但除非这是一个重复代码的大循环,否则你可能不会注意到差异。

3 - 是的。在第一个示例中,您正在搞乱调用堆栈。这个例子通过冒泡异常来保持堆栈的完整性,而不是抛出新的异常。

如果你真的没有做任何其他事情,那么我找到的只有一个优势:你可以在 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

您会注意到前两个例外工作方式相同。所以,“扔;”对于向上移动堆栈的异常,它不会改变任何东西。然而,“throw 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()是一个自定义类,它会记录异常或通过电子邮件发送警报或其他内容。

我认为重点是确保只抛出一种TYPE异常。这是一个非常糟糕的反模式恕我直言

e.g。

try
{
    throw XYZ();
}
catch(Exception e)
{
    throw e;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top