Catch Exception treatment
使用的区别是什么
1 2 3 4 5
| catch(Exception ex)
{
...
throw ex;
} |
并使用
1 2 3 4 5
| catch // might include (Exception)
{
...
throw;
} |
- DUP?stackoverflow.com/questions/730250/…
throw ex从该点重新抛出异常对象。这通常是不好的,因为它会破坏导致原始问题的有用调用堆栈信息。
throw从实际抛出的点释放原始捕获的异常。它将调用堆栈信息保留到该点,而不是保留到捕获的点。
catch(Exception)和catch本质上是相同的,除了第一个显然给了你一个例外对象,第二个则没有。但两者都会捕捉到所有的例外。它们与catch(SomeKindOfException)不同,后者只捕获特定类型(或从该类型派生的更特定类型)的异常。这是最好的情况,如:
1 2 3 4 5 6 7 8 9 10 11
| 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)相同。
- 谢谢。。。主要是关于调用堆栈的信息是我的疑问,但是每件事都很有用
- @埃里希,你有没有扔过一些不是从例外中得到的东西?
- 我没有,虽然这是一个差异,他要求的差异。说实在的,我很确定,不可能抛出非异常的东西,所以我不知道为什么这种语言是这样设计的。
- @雷克斯:如果你在我下面的帖子上查看我的评论,很明显这只是1.1中的意思。自2.0以来,非CLS异常被包装在异常类型中,但以前它们不一定被包装。所以很明显,空手抓鱼确实在某一点上做了一些有意义的事情。
在框架1.x中,使用不带参数的catch可以捕获从非托管代码引发的异常。从框架版本2(IIRC)开始,所有非托管异常都包装在托管异常对象中,因此不再使用无参数捕获。
无参数引发不特定于无参数catch,它可以用于任何catch块。区别在于,当使用throw;追溯异常时,它不会覆盖最初抛出异常时的堆栈跟踪,因此这是重新引发异常的正确方法。
不要在catch块中使用throw ex;,而是抛出一个新创建的异常,其中包含要添加的信息,原始异常作为内部异常。这样,你就得到了最初的失败点,以及你抓住它并重犯它的点。
因此,您不应该在问题的示例中使用任何组合。您总是指定异常类型,并且只需追溯异常:
1 2 3 4
| catch (Exception ex) {
...
throw;
} |
或者抛出带有内部异常的新异常:
1 2 3 4
| catch (Exception ex ) {
...
throw new ApplicationException ("Ooops!", ex );
} |
请注意,您应该很少捕获异常基类,而是一个更具体的异常类,它适用于您预期的错误。通常,捕捉一个你不知道如何处理的异常是没有意义的。
- 我不同意,但我仍然觉得无参数捕捉很有用。我用LotusNotes编程,它喜欢为流控制向我抛出异常。由于我似乎找不到它抛出的所有异常的列表,所以我必须使用无参数捕获来防止组件失败并破坏整个应用程序。
- @杰森:流控制似乎是抛出异常的一个奇怪原因…无论如何,无法映射到托管异常的非托管异常将转换为ComException类。作为最后一种方法,您可以捕获基类异常,这比无参数捕获要好,因为它提供了有关错误的一些小信息。
- 但捕获异常是否与捕获所有内容一样?我想如果你抛出一个非异常类型,它在实际抛出之前就被包装在一个类型中了…
- @RCIX:区别在于,当捕获异常时,您会得到对异常对象的引用;当您使用无参数异常时,您将完全没有关于异常的信息。
好吧,第一个将删除堆栈跟踪,并将其替换为抛出的位置。第二个将在不改变堆栈跟踪的情况下抛出异常。
另外,"catch"将捕获抛出的任何内容,无论是否为异常。
第二种方法实际上相当于执行"catch(object)"。
- (不是我投的反对票)在.NET中的任何东西都是一个对象;即使是"throw 1"也会被"catch(object)"捕获。
- 正是我的意思!catch(异常)将错过"throw 1"或"throw"blah。
- 也许理论上是真的,但你有没有扔过或抓住过1?
- 我不是投你反对票的人,我想我不知道是谁干的。但我认为这是因为catch(对象),在基本上任何类中,您都希望放入catch mush扩展系统中。
- 哈哈,看起来你真的不能扔1,那一定是C++的记忆。谢谢Rex M
- 不可能抛出或捕获非System.Exception派生的内容。编译器错误CS0155
- @jmayor:没错,我认为我没有把它作为有效代码传递,我提到了一个普通的catch等价于伪代码。此外,即使是"throw 1"也是无效的代码,所以我不知道为什么空白catch是"catch对象"。至于投反对票:我比接受的答案包括更多的分歧,包括雷克斯给出的答案,甚至超过10秒击败他,所以我仍然不理解投反对票。
- 更奇怪的是:显然在vb.net中,catch(exception)和catch是相同的。根据clr团队的博客(msdn.microsoft.com/en-us/library/ms229005.aspx和blogs.msdn.com/clr team/archive/2009/02/19/…),空捕获将捕获"非cls异常"。显然,在.NET 1.1中,从已使用的库(COM和其他东西?)中抛出的非CLS异常不是自动包装的。
- +1以抵消下投,大概是因为你的抓捕(目标)主张……顺便说一下,这是100%正确的。事实上,这正是C编译器所做的。
第一个重置引发的异常中的堆栈跟踪属性
据我所知,这是同一件事(使用例外…因为所有的异常都来自那个类)。当你只抓到一个例外的孩子时,情况就不同了…或者当你有几个"抓"着不同的孩子。也可能是捕获异常、修改消息并将其抛出。
- 能解释一下-1吗?我想从我的错误中吸取教训。谢谢
- 看雷克斯·M的回答。基本上,throw ex是坏的,因为它破坏了调用堆栈。