pal*_*wim 6 c# idisposable using-statement
我问了一个关于从函数中返回一个Disposable(IDisposable)对象的问题,但是如果我在那里提出这个问题,我认为我会讨论这个问题.
我创建了一些示例代码:
class UsingTest
{
public class Disposable : IDisposable
{
public void Dispose()
{
var i = 0;
i++;
}
}
public static Disposable GetDisposable(bool error)
{
var obj = new Disposable();
if (error)
throw new Exception("Error!");
return obj;
}
}
Run Code Online (Sandbox Code Playgroud)
我故意用这种方式编码,因为我打电话给:
using (var tmp = UsingTest.GetDisposable(true)) { }
Run Code Online (Sandbox Code Playgroud)
使用调试器,我注意到该Dispose方法永远不会执行,即使我们已经实例化了一个Disposable对象.如果我正确地理解了这个目的Dispose,如果这个类实际上已经打开了句柄之类的东西,那么我们一旦完成它们就不会关闭它们.
我问这个问题是因为这种行为符合我的期望,但在相关问题的答案中,人们似乎表明using会照顾一切.
如果using仍然以某种方式处理所有这些,有人可以解释我错过了什么?但是,如果这段代码确实会导致资源泄漏,你会如何建议我编写代码GetDisposable(条件是我必须实例化IDisposable对象并运行可能在return语句之前抛出异常的代码)?
Gre*_*ley 11
它从未被调用的原因是因为你分配它的方式.永远不会分配"tmp"变量,因为GetDisposable(bool)函数永远不会返回,因为您抛出了异常.
如果你要说以下,
using (var tmp = new Disposable())
{
throw new ArgumentException("Blah");
}
Run Code Online (Sandbox Code Playgroud)
然后你会看到IDisposable::Dispose() 确实被调用了.
要理解的基本要素是using块必须获得IDisposable对象的有效引用.如果发生了一些异常,因此using块中声明的变量没有被赋值,那么你就不幸了,因为using块不知道该IDisposable对象.
至于IDisposable从函数返回一个对象,你应该使用catch函数内部的标准块来Dispose()在发生故障时调用,但显然你不应该使用一个using块,因为这会在你准备好之前处理对象.
根据您想要的语义GetDisposable,这可能是我实现它的方式:
public static Disposable GetDisposable(bool error)
{
var obj = new Disposable();
try
{
if (error)
throw new Exception("Error!");
return obj;
}
catch (Exception)
{
obj.Dispose();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)