首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我不太理解使用/Disposable对象的工作原理

我不太理解使用/Disposable对象的工作原理
EN

Stack Overflow用户
提问于 2010-11-19 08:14:09
回答 6查看 947关注 0票数 6

我问了一个关于returning a Disposable (IDisposable) object from a function的问题,但我认为如果我在那里提出这个问题,我会混淆讨论。

我创建了一些示例代码:

代码语言:javascript
复制
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;
    }
}

我故意这样编写,因为然后我调用:

代码语言:javascript
复制
using (var tmp = UsingTest.GetDisposable(true)) { }

使用调试器时,我注意到即使我们已经实例化了一个Disposable对象,Dispose方法也从不执行。如果我正确理解了Dispose的用途,如果这个类实际上有打开的句柄之类的,那么我们不会在完成它们之后立即关闭它们。

我问这个问题是因为这个行为符合我的预期,但在对相关问题的回答中,人们似乎表明using会处理一切。

如果using仍然以某种方式处理这一切,有人能解释一下我错过了什么吗?但是,如果这段代码确实可能导致资源泄漏,您会如何建议我编写GetDisposable (条件是我必须实例化IDisposable对象并运行可能在返回语句之前抛出异常的代码)?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-11-19 08:23:03

根据您想要的GetDisposable语义,我可能会这样实现它:

代码语言:javascript
复制
public static Disposable GetDisposable(bool error)
{
    var obj = new Disposable();

    try
    {
        if (error)
            throw new Exception("Error!");

        return obj;
    }
    catch (Exception)
    {
        obj.Dispose();
        throw;
    }
}
票数 4
EN

Stack Overflow用户

发布于 2010-11-19 08:18:17

它永远不会被调用的原因是你分配它的方式。"tmp“变量根本不会被分配,因为由于抛出了一个异常,所以GetDisposable(bool)函数永远不会返回。

如果你说下面这句话,

代码语言:javascript
复制
using (var tmp = new Disposable())
{
    throw new ArgumentException("Blah");
}

然后,您将看到IDisposable::Dispose()确实被调用了。

要理解的基本内容是,using块必须获得对IDisposable对象的有效引用。如果发生了一些异常,导致在using块中声明的变量没有被赋值,那么您就倒霉了,因为using块将不知道IDisposable对象。

至于从函数返回IDisposable对象,您应该在函数内部使用标准的catch块在失败的情况下调用Dispose(),但显然不应该使用using块,因为这将在您自己准备好之前释放对象。

票数 11
EN

Stack Overflow用户

发布于 2010-11-19 08:23:14

这是因为从未赋值过tmp变量。这是使用一次性对象时需要注意的问题。GewtDisposable更好的定义应该是:

代码语言:javascript
复制
public static Disposable GetDisposable(bool error)
{
    var obj = new Disposable();

    try
    {
        if (error)
            throw new Exception("Error!");
        return obj;
    }
    catch
    {
        obj.Dispose();
        throw;
    }
}

因为它确保了obj被释放。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4221005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档