C#"使用"语法

时间:2020-03-06 14:53:05  来源:igfitidea点击:

使用会捕获还是抛出异常? IE。

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

如果streamreader抛出异常,是使用还是抛出了异常,以便调用函数可以处理它?

解决方案

它被抛出。

如果我们没有专门捕获异常,则会将其抛出堆栈,直到发生某种情况为止

"使用"允许异常通过。它的作用类似于try / finally,最终将已使用的对象放置在这里。因此,它仅对实现" IDisposable"的对象适用/有用。

使用语句不吃异常。

所有"使用"操作都将对象范围限制为using块,并在对象离开该块时自动在该对象上调用Dispose()。

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

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

它不处理异常,但是让异常通过。

"使用"不会捕获异常,它只是在发生未处理的异常的情况下处置资源。

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

当我们看到一个using语句时,请考虑以下代码:

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

因此,真正的答案是,除了using块的主体中​​抛出的异常之外,它什么都不做。它不处理它或者将其扔掉。

它引发异常,因此包含方法需要处理该异常,或者将其传递到堆栈中。

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! 
}

"使用"保证*,即使抛出异常,创建的对象也将放置在块的末尾。没有捕获到异常。但是,如果我们自己尝试捕获它,则需要谨慎行事。由于任何捕获异常的代码都在using语句定义的作用域块之外,因此对象将对该代码不可用。

*除非发生电源故障,核大屠杀等常见嫌疑

我们可以想象使用try ... finally块而不使用catch块。在finally块中,将调用IDisposable.Dispose,并且由于没有catch块,因此任何异常都将抛出堆栈。

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

但是要注意的一件事是,如果初始化表达式中发生异常,则不会在表达式变量上调用Dispose()方法。这几乎总是我们想要的行为,因为我们不想打扰放置一个并非实际创建的对象。但是,在复杂的情况下可能会出现问题。也就是说,如果多个初始化被埋在构造函数中,并且某些初始化在引发异常之前成功完成,则此时可能不会发生Dispose调用。但是,这通常不是问题,因为构造函数通常保持简单。