48

using 是捕获异常还是抛出异常?IE

using (StreamReader rdr = File.OpenText("file.txt"))
{
 //do stuff
}

如果流读取器抛出异常,它是通过使用捕获还是抛出以便调用函数可以处理它?

4

11 回答 11

64

当您看到 using 语句时,请考虑以下代码:

StreadReader rdr = null;
try
{
    rdr = File.OpenText("file.txt");
    //do stuff
}
finally
{
    if (rdr != null)
        rdr.Dispose();
}

所以真正的答案是它不会对 using 块的主体中​​抛出的异常做任何事情。它不处理它或重新抛出它。

于 2008-09-29T17:00:17.617 回答
35

using 语句不吃异常。

所有“使用”所做的只是将您的对象限定为 using 块,并在对象离开块时自动调用对象的 Dispose()。

但是有一个问题,如果线程被外部源强行中止,则可能永远不会调用 Dispose。

于 2008-09-29T16:58:43.423 回答
16

using允许异常沸腾。它的作用类似于 try/finally,finally 处理使用的对象。因此,它仅适用于实现IDisposable.

于 2008-09-29T16:57:44.860 回答
6

它抛出异常,因此您的包含方法需要处理它,或者将其传递到堆栈中。

try
{
    using (
        StreamReader rdr = File.OpenText("file.txt"))
    { //do stuff 
    }
}
catch (FileNotFoundException Ex)
{
    // The file didn't exist
}
catch (AccessViolationException Ex)
{
    // You don't have the permission to open this
}
catch (Exception Ex)
{
    // Something happened! 
}
于 2008-09-29T17:01:17.677 回答
4

在 using 语句的初始化表达式中引发的任何异常都将按预期向上传播方法范围和调用堆栈。

不过要注意的一件事是,如果初始化表达式中发生异常,则不会在表达式变量上调用 Dispose() 方法。这几乎总是您想要的行为,因为您不想费心处理实际上未创建的对象。但是,在复杂的情况下可能会出现问题。也就是说,如果在构造函数中隐藏了多个初始化,并且一些初始化在抛出异常之前成功,那么此时可能不会发生 Dispose 调用。不过,这通常不是问题,因为构造函数通常保持简单。

于 2008-09-29T17:05:25.187 回答
3

在您的示例中,如果File.OpenText抛出,Dispose不会调用。

如果异常发生在//do stuffDispose 被调用。

在这两种情况下,异常通常会传播到范围之外,就像没有using语句一样。

于 2011-05-04T03:58:51.783 回答
2

如果您没有专门捕获异常,它将被抛出堆栈,直到发生某些事情

于 2008-09-29T16:57:19.230 回答
2

除了清理其范围内的内容外, using 不会干扰异常处理。

它不处理异常,但允许异常通过。

于 2008-09-29T16:58:49.960 回答
2

using保证*创建的对象将在块的末尾被释放,即使抛出异常也是如此。捕获异常。但是,如果你试图自己抓住它,你需要小心你所做的事情。由于任何捕获异常的代码都在using语句定义的范围块之外,因此您的对象将不可用于该代码。

*除了停电,核浩劫等常见的嫌疑人

于 2008-09-29T17:02:07.313 回答
1

你可以想象在没有 catch 块的情况下使用try...finally块。在 finally 块中,IDisposable.Dispose 被调用,并且由于没有 catch 块,任何异常都会被抛出堆栈。

于 2008-09-29T17:03:49.120 回答
0

“使用”不会捕获异常,它只是在发生未处理的异常时处理资源。

也许问题是,如果声明中也出现错误,它会处理括号中分配的资源吗?不过,很难想象两者都会发生。

于 2008-09-29T16:59:40.597 回答