C# 在.NET中,尝试/捕获只是重复捕获,有什么好处吗

C# 在.NET中,尝试/捕获只是重复捕获,有什么好处吗,c#,.net,try-catch,C#,.net,Try Catch,可能重复: 我有时会遇到这样的C代码: try { // Some stuff } catch (Exception e) { throw e; } 我知道可以做一些事情,比如记录异常消息,然后重新播放它。我说的是一个只会重现异常的捕获。我不认为这有什么意义。我有三个问题: 1) 这有什么好处吗 2) 这会减慢代码的速度吗 3) 如果挡块如下所示,会

可能重复:

我有时会遇到这样的C代码:

        try
        {
            // Some stuff
        }
        catch (Exception e)
        {
            throw e;
        }
我知道可以做一些事情,比如记录异常消息,然后重新播放它。我说的是一个只会重现异常的捕获。我不认为这有什么意义。我有三个问题:

1) 这有什么好处吗

2) 这会减慢代码的速度吗

3) 如果挡块如下所示,会有什么不同吗

        catch (Exception)
        {
            throw;
        }

如果你在抓捕过程中什么都不做就不会了。。。但这通常用于在catch中执行其他操作,例如在重新刷新之前进行日志记录或其他类型的异常处理。

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

    catch (Exception)
    {
        throw;
    }
然而,这会在不包含原始堆栈跟踪的情况下重新引发异常:

    catch (Exception e)
    {
        throw e;
    }
抛出
通常有很好的理由因为您可以在重新引发异常之前记录异常或执行其他操作。我不知道有什么好的理由抛出e因为您将清除有价值的堆栈跟踪信息。

当然

大多数情况下,您希望在抛出异常之前记录异常,并可能从方法中记录一些变量值


但是,仅仅抓住它然后扔掉它并不能给你带来很多好处。

就像那样,没有。但是,你可能想这样做:

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

其中LogException()是一个自定义类,用于记录异常或通过电子邮件发送警报或其他信息。

我使用这种技术,以便在调试时在抛出时放置断点。有时我会在完成后删除它…

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


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

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

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


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

我认为关键是要确保只抛出一种类型的异常。这是一个非常糟糕的反模式IMHO

e、 g


如果你真的什么都不做,那么我只发现了一个好处:你可以在
throw
行上设置一个断点。它使它非常具体(而不是在抛出异常类型时中断)

不过,我只会在调试时这样做,然后将代码还原回来。

有什么好处吗 一般来说,不会。这个模式所做的就是将堆栈跟踪重置到新抛出的点。这只会使开发人员更难找到问题的根源

它会降低代码的速度吗 到底是什么?可能地通过任何可测量的差异来减缓它?没有

如果捕捉块如下所示,会有什么不同吗?
是的,这种捕获基本上是完全多余的。它将重新显示异常,该异常将保持原始堆栈跟踪,并且对应用程序没有可察觉的影响

记录日志通常很好。另外,如果您在重新抛出中省略了参数,那么它不会改变e的堆栈跟踪

有时,您希望允许通过某些类型进行操作,例如,除了FooException之外,这里还有对所有内容的特殊处理:

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

我写了一个快速测试来显示差异。以下是测试代码:

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;”不会改变任何东西,只要异常在堆栈中向上移动。然而,“throw ex3;”会导致报告的异常不同,从而更改异常的堆栈跟踪。

See-并且后者几乎不应该被使用,尽管有人可能会说,在您介绍的化身中也不应该使用前者(至少不需要在混合中添加某种形式的日志)。@Andrew,正如我所理解的,变量e是指向堆上相同异常对象的指针。。。您是说在堆上创建了一个新的异常对象吗?或者只是创建了一个新的ref变量“e”?如果是前者,你对这则花絮有什么参考吗?@Charles-很好地指出-我一直认为这是一个新的例外,但一些调查帮助我了解到,在这两种情况下,它实际上是完全相同的例外情况。@Andrew,我很好奇,(我将对此做更多的研究),关于为什么第一种语法包含堆栈跟踪,而第二种语法却没有,我个人很喜欢这种内部异常。使用您自己的消息引发新异常,但附加导致错误的原始原因的异常。为什么不使用stacktrace来确定生成引发的代码行?这个技巧不是要知道引发异常的位置(您可以为此启用CLR异常调试)-当您有断点时,您有QuickWatch,这通常足以解决异常的原因。这不会捕获任何类型的异常并重新刷新它吗?这就是为什么该语句没有任何意义。它会捕获任何类型的异常并将其作为“exception”类型的异常重新刷新,直到删除类型信息。我想最后一句话是+1!
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