【问题标题】:Catch Exception treatment捕获异常处理
【发布时间】:2010-12-11 22:38:21
【问题描述】:

使用有什么区别

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

并使用

catch   //  might include  (Exception) 
{
   ...
   throw;
}

【问题讨论】:

标签: c#


【解决方案1】:

好吧,第一个将删除堆栈跟踪,并将其替换为您的 throw 所在的位置。第二个将抛出异常而不改变堆栈跟踪。

此外,“catch”将捕获抛出的任何东西,无论它是否是异常。

第二个其实相当于做“catch(object)”。

【讨论】:

  • (不是我的反对意见).NET 中的任何东西都是对象;即使是“throw 1”也会被“catch(object)”捕获
  • 正是我的观点! catch(Exception) 会错过一个 'throw 1' 或一个 'throw "blah"'。
  • 理论上也许是对的,但你有没有扔过或抓过1?
  • 好吧,我不是那个让你失望的人,我想我不知道是谁做的。但我认为这是因为 catch(object) ,基本上任何你想放入 catch 的类中都可以扩展 System.Exception
  • 哈哈,看来你真的不能扔1;那一定是来自 C++ 的内存。谢谢雷克斯 M
【解决方案2】:

第一个重置抛出异常中的堆栈跟踪属性

【讨论】:

    【解决方案3】:

    throw ex 从该点重新抛出异常对象。这通常很糟糕,因为它破坏了导致原始问题的有用调用堆栈信息。

    throw 释放原始捕获的异常,从它实际抛出的那一点开始。它将调用堆栈信息保留到该点,而不是您捕获的点。

    catch(Exception)catch 本质上是一样的,除了显然第一个给你异常对象做某事,而第二个没有。但两者都会捕获所有异常。它们与catch(SomeKindOfException) 不同,后者只会捕获该特定类型(或更具体的从该类型派生的类型)的异常。这最适合以下情况:

    try
    {
        //some file operation
    }
    catch(FileNotFoundException fnfex)
    {
        //file not found - we know how to handle this
    }
    //any other kind of exception,
    //which we did not expect and can't know how to handle,
    //will not be caught and throw normally
    

    【讨论】:

    • 此外,catch(Exception) 限制了可以捕获的范围。普通的 catch 绝对会捕获任何抛出的东西,与 catch(object) 基本相同
    • 谢谢...主要是关于调用堆栈的信息是我的疑问,但一切都非常有用
    • @Erich 你有没有抛出不是从异常派生的东西?
    • 我没有,虽然有区别,他要求区别。老实说,我很确定不可能抛出不是源自异常的东西,所以我不知道为什么语言是这样设计的。
    • @Rex:如果您查看我对下面帖子的评论,显然这只是 1.1 中的内容。从 2.0 开始,非 CLS 异常被包装在 Exception 类型中,但以前它们不一定被包装。显然,空的 catch 确实在某一时刻做了一些有意义的事情。
    【解决方案4】:

    据我所知,这是一回事(使用 Exception.. 因为所有异常都派生自该类)。当您仅捕获 Exception 的一个孩子时,它会变得不同......或者当您有几个“捕获”捕获不同的孩子时。 也可能是您捕获了异常,修改了消息,然后将其丢弃。

    【讨论】:

    • 想解释一下 -1 吗?我想从我的错误中学习。谢谢
    • 查看 Rex M 的回答。基本上throw ex 很糟糕,因为它破坏了调用堆栈。
    【解决方案5】:

    在框架 1.x 中使用不带参数的 catch 来捕获非托管代码引发的异常非常有用。从框架版本 2 (IIRC) 开始,所有非托管异常都包装在托管 Exception 对象中,因此不再使用无参数捕获。

    无参数 throw 并不特定于无参数 catch,它可以在任何 catch 块中使用。不同之处在于,当使用throw; 追溯异常时,它不会覆盖最初引发异常时的堆栈跟踪,因此这是重新引发异常的正确方法。

    您应该抛出一个新创建的异常,其中包含您要添加的信息,而不是在 catch 块中使用 throw ex;,并将原始异常作为内部异常。这样一来,您既可以得到最初的失败点,也可以得到抓住它并重新抛出它的点。

    因此,您绝不应该在问题的示例中使用任何一种组合。您总是指定异常类型,或者只是追溯异常:

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

    或者你抛出一个带有内部异常的新异常:

    catch (Exception ex) {
       ...
       throw new ApplicationException("Ooops!", ex);
    }
    

    请注意,您应该很少捕获 Exception 基类,而是更具体的异常类,它适合您预期的错误。捕获您不知道如何处理的异常通常是没有意义的。

    【讨论】:

    • 我不同意,但我仍然发现无参数捕获很有用。我使用 Lotus Notes 进行编程,它喜欢向我抛出异常以进行流控制。因为我似乎找不到它抛出的所有异常的列表,所以我必须使用无参数的 catch 来防止组件失败并破坏整个应用程序。
    • @jasonh:流控制似乎是引发异常的一个奇怪原因......无论如何,无法映射到托管异常的非托管异常被转换为 COMException 类。作为最后的手段,您可以捕获基类 Exception,这比无参数捕获更好,因为它为您提供了一些关于错误的少量信息。
    • 但是捕捉异常与捕捉一切不一样吗?我想如果你抛出一个非异常类型,它会在实际抛出之前被包装在一个中......
    • @RCIX:不同之处在于,当捕获 Exception 时,您会获得对 Exception 对象的引用,而当您使用无参数异常时,您根本不会获得有关该异常的任何信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 2017-05-02
    • 2018-02-06
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多