代码之家  ›  专栏  ›  技术社区  ›  Justin Dearing

在.NET中,尝试/捕获只会再次引发捕获的情况有什么好处吗[重复]

  •  5
  • Justin Dearing  · 技术社区  · 15 年前

    可能重复:
    Why catch and rethrow Exception in C#?

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

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

    我理解可以做一些事情,比如记录异常消息,然后重新显示它。我说的是一个只会重新引发异常的捕获。我看不出有什么意义。我有三个问题:

    1)这有什么好处吗

    2)这对代码有什么影响吗?

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

            catch (Exception)
            {
                throw;
            }
    
    12 回复  |  直到 15 年前
        1
  •  20
  •   Andrew Hare    15 年前

    这会使 准确的 相同的例外:

        catch (Exception)
        {
            throw;
        }
    

    然而,这会在没有原始堆栈跟踪的情况下重新引发异常:

        catch (Exception e)
        {
            throw e;
        }
    

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

        2
  •  3
  •   Charles Bretana    15 年前

    如果你在抓捕中什么都不做…但这通常用于在重新执行捕获之前执行捕获中的其他操作,如日志记录或其他类型的异常处理。

        3
  •  2
  •   lotsoffreetime    15 年前

    我使用这种技术,以便在调试时在抛出上放置一个断点。有时候我做完后就把它取下来…

        4
  •  2
  •   Garry Shutler    15 年前

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

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

        5
  •  2
  •   JaredPar    15 年前

    有什么优势吗

    一般来说,不是。所有这些模式都将把堆栈跟踪重置到新的抛出点。这只会让开发人员更难找到问题的根源。

    它会减慢代码的速度吗

    完全?可能。通过任何可测量的差异降低速度?不。

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

    是的,这种捕获基本上是完全多余的。它将重新引发异常,该异常将维护原始堆栈跟踪,并且对应用程序没有可察觉的影响。

        6
  •  1
  •   Scott Ivey    15 年前

    我看不出有什么优势。如果您没有处理异常,请关闭Try/Catch。这个例子的另一个问题是,您不会抛出实际的异常,而是抛出一个新的异常。

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

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

        7
  •  1
  •   Jon Skeet    15 年前

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

    不过,我只在调试时这样做,然后恢复代码。

        8
  •  1
  •   John Fisher    15 年前

    我写了一个快速测试来显示不同之处。测试代码如下:

    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;”会导致报告的异常不同,从而更改异常的堆栈跟踪。

        9
  •  1
  •   mckamey    15 年前

    它经常适合伐木。另外,如果在re-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);
    }
    
        10
  •  0
  •   Brandon    15 年前

    当然。

    通常,您希望在抛出异常之前记录它,并可能从该方法中记录一些变量值。

    不过,仅仅是抓住它扔出去,并不能给你带来很多好处。

        11
  •  0
  •   Dan Diplo    15 年前

    就像那样,不,但是,你可能想这样做:

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

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

        12
  •  -1
  •   Glen    15 年前

    我认为重点是确保只抛出一种类型的异常。这是一个很糟糕的反模式imho

    例如

    try
    {
        throw XYZ();
    }
    catch(Exception e)
    {
        throw e;
    }