繁体   English   中英

了解一次性物品

[英]Understanding disposable objects

我已经在 SO 中查看了类似这样的问题,即使我发现了很多,其中任何一个都为我解决了这个问题。

让我们假设我有这个代码:

public class SuperObject : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing) { }
}
  • 我需要在SuperObject上使用protected virtual void Dispose(bool)吗? 因为那里真的没有什么可以处理的。
public interface ICustom : IDisposable { }
public class Custom : ICustom
{
    public SuperObject Super { get; protected set; }

    public Custom()
    {
        Super = new SuperObject();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public virtual void Dispose(bool disposing)
    {
        if (!disposing) return;

        if (Super != null)
            Super.Dispose();
    }
}
public class Foo
{
    public Foo()
    {
        using (var c = new Custom())
        {
            //do magic with c
        }
    }
}

现在,如果我想/需要/尝试在System.Web.Mvc.Controller这样已经实现并已经实现 IDisposable 的类上使用Custom会发生什么?

public class Moo : Controller
{
    Custom c;

    public Moo()
    {
        c = new Custom();
    }

    // Use c throughout this class        
}

如何在Moo正确处理c

正常的方法是应用标准的 IDisposable 实现- 但是,这实际上只有在您的类或从它派生的某个类将使用非托管资源时才是必要的 -这种情况实际上非常罕见(当这种情况确实适用时,最好将其包装起来)类中的非托管资源,该类具有完整的标准 IDisposable 实现)。

因此,假设您不处理非托管资源(原始文件句柄、全局分配的内存等)并且只处理一次性成员(即具有托管资源并实施 IDisposable),那么您可以安全地获得一种最小实现的方法IDispose - 即:

只需一个 void Dispose() 方法。 在该方法中,只需在可处理成员上调用 dispose,然后在基类上调用 Dispose(如果它是可处理的)。 如果您有一个类层次结构,可以将这个 Dispose 设为虚拟。 不需要有 Dispose(bool) 方法。 也不需要检查对象是否已被处理——因为您所做的只是在其他对象上调用 dipsose,而那些实现将进行该检查。

如果您不喜欢最简单的方法,则应用标准的完全实现(但这不是绝对必要的)。 即要么做一个标准的实现,因为你坚持遵循推荐的方法,要么做一个简单的最小(但正确)的实现 - 但不要在两者之间做任何事情(即不标准,不简单或不正确)!

有关更多详细信息,请参阅此问题: Minimal IDispose implimenation for managed resources only

因此,在您的情况下,以下是最小的实现:

public class SuperObject : IDisposable {
    public void Dispose() {
        // Dispose code...just call dispose on dispoable members.
        // If there are none then no need to implement IDisposable!
    }
}

public interface ICustom : IDisposable { }
public class Custom : ICustom {
    public SuperObject Super { get; protected set; }

    public Custom() {
        Super = new SuperObject();
    }

    public void Dispose() {
        if (Super != null)
            Super.Dispose();
    }
}  

public class Moo : Controller {
    Custom c;

    public Moo() {
        c = new Custom();
    }

    public Dispose() {
        if (c!=null)
            c.Dispose()
        base.Dispose();       
    }
}

请注意,如果 Super 对象没有任何一次性资源,那么实现 IDisposable 和拥有 Dispose 方法就没有意义。 如果海关唯一的一次性对象是 SuperObject,那么同样适用于那里,同样的逻辑再次适用于 Moo。 最后,如果以上所有内容都适用并且周围没有其他一次性物品,那么您真正需要的是:

  public class Moo : Controller {
        Custom c;
    
        public Moo() {
            c = new Custom();
        }
    
        public Dispose() {
           base.Dispose();       
        }
    }

如何在Moo正确处理c

public class Moo : Controller
{
    Custom c;

    public Moo()
    {
        c = new Custom();
    }

    // Use c throughout this class    


    protected override Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
           c.Dispose()
    }
}

这也回答了您的第一个问题, Controller需要使其Dispose(bool)方法protected virtual否则上述方法是不可能的。

但有几点说明:

  • 你没有任何isDisposed逻辑。 只进行一次处理是个好主意,您可能希望捕获使用后处理。
  • 省略析构函数(终结器)本身是一个好主意,但您现在有额外的约束,即派生类不应拥有非托管资源。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM