C#“使用”句法
-
02-07-2019 - |
题
使用是否捕获异常或抛出异常?即
using (StreamReader rdr = File.OpenText("file.txt"))
{
//do stuff
}
如果streamreader抛出异常是通过使用或抛出来捕获的,那么调用函数可以处理它吗?
解决方案
使用语句不会吃异常。
全部“使用”将你的对象作为使用块的范围,并在对象离开块时自动调用Dispose()。
但是,如果线程被外部源强制中止,则可能永远不会调用Dispose。
其他提示
当您看到using语句时,请考虑以下代码:
StreadReader rdr = null;
try
{
rdr = File.OpenText("file.txt");
//do stuff
}
finally
{
if (rdr != null)
rdr.Dispose();
}
所以真正的答案是它不会对使用块体内抛出的异常做任何事情。它没有处理它或重新抛出它。
using
允许异常沸腾。它就像一个try / finally,最终处理使用过的对象。因此,它仅适用于实现 IDisposable
的对象。
它抛出异常,因此要么包含的方法需要处理它,要么将它传递给堆栈。
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语句的初始化表达式中抛出的任何异常都会按预期向上传播方法范围和调用堆栈。
但要注意的一件事是,如果初始化表达式中发生异常,则不会在表达式变量上调用Dispose()方法。这几乎总是您想要的行为,因为您不想打扰处理实际未创建的对象。但是,在复杂的情况下可能存在问题。也就是说,如果多个初始化被隐藏在构造函数中并且一些初始化在抛出异常之前成功,那么此时可能不会发生Dispose调用。但这通常不是问题,因为构造函数通常很简单。
在您的示例中,如果 File.OpenText
抛出, Dispose
将不被调用。
如果 // do stuff
中发生异常,则会调用 Dispose
。
在这两种情况下,异常通常都会传播到范围之外,就像没有使用语句一样。
如果你没有专门捕获异常,它会被抛出堆栈直到某些东西
除了清理其范围内的东西外,使用不会干扰异常处理。
它不处理异常,但允许异常通过。
使用
保证*即使抛出异常,创建的对象也将被置于块的末尾。例外情况是未被捕获。但是,如果你试图自己捕捉它,你需要小心你所做的事情。由于捕获异常的任何代码都在 using
语句定义的范围块之外,因此该代码将无法使用该对象。
您可以将使用想象为没有catch块的 try ... finally 块。在finally块中,调用了IDisposable.Dispose,并且由于没有catch块,所以在栈中抛出任何异常。
"使用"不捕获异常,只是在未处理的异常情况下处理资源。
也许问题是,如果声明中也出现错误,它会处理括号中分配的资源吗?但是很难想象两者都会发生。