关于c#:Catch异常处理


Catch Exception treatment

使用的区别是什么

1
2
3
4
5
catch(Exception ex)
{
   ...
   throw ex;
}

并使用

1
2
3
4
5
catch   //  might include  (Exception)
{
   ...
   throw;
}


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


在框架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);
}

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


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

另外,"catch"将捕获抛出的任何内容,无论是否为异常。

第二种方法实际上相当于执行"catch(object)"。


第一个重置引发的异常中的堆栈跟踪属性


据我所知,这是同一件事(使用例外…因为所有的异常都来自那个类)。当你只抓到一个例外的孩子时,情况就不同了…或者当你有几个"抓"着不同的孩子。也可能是捕获异常、修改消息并将其抛出。