理解一次性对象 [英] Understanding disposable objects

查看:179
本文介绍了理解一次性对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


$ b $

我已经看过这个问题了,甚至我发现了很多,其中任何一个都会为我解释这件事。 b

假设我有这样的代码:

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


protected void Dispose(bool disposing){}
}




  • 是否需要 SuperObject protected virtual void Dispose(bool) $ C>?
  • 公共介面ICustom:IDisposable {}



     公共类自定义:ICustom 
    {
    public SuperObject Super {get;保护组; }

    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();


    $ / code $ / pre

     < 













    $ b $ / do magic with c
    }
    }
    }

    现在如果我希望/需要/尝试对 System.Web.Mvc.Controller 类使用 Custom ,会发生什么情况已经实现并实现了IDisposable?

      public class Moo:Controller 
    {
    自定义c;

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

    //在整个班级中使用c
    }

    如何在 Moo

    中正确处置 c

    解决方案

    常规方法是将标准IDispoable实现 - 然而,只有当你的类或源自它的某个类将使用非托管资源时,这才是真正必要的 - 这种情况是事实上非常罕见(当这种情况发生时,最好将非托管资源包装在自己的具有完整标准IDisposable实现的类中)。



    所以假设你没有处理非托管资源(原始文件句柄,全局分配memeory等),只处理一次性成员(即已管理资源并实现IDisposable)的成员,那么你可以安全地与上午IDispose的简单实现 - 即:

    只需要一个void Dispose()方法。在该方法中,只需对可释放成员调用dispose,然后在基类上处理Dispose。如果你有一个类层次结构可以使这个Dispose虚拟。没有必要有一个Dispose(布尔)方法。也没有任何需要检查对象是否被丢弃 - 因为你所做的只是在其他对象上调用dipsose,并且这些实现将会执行该检查。

    如果您不喜欢简单的appraoch,那么应用标准的完整implimentation(但并非严格必要)。或者做一个标准implimentation,因为你坚持使用推荐的方法,或者做一个简单的最小(但是正确的)实现 - 但不要在两者之间做一些事情(即不是标准的,不是简单的或不正确的)!



    有关详情,请参阅此问题:仅限管理资源的最小IDispose限制



    所以在你的情况下,以下是最小的implimentation:

      public class SuperObject:IDisposable {
    public void Dispose(){
    //处理代码...只需在Dispoable成员上调用dispose。
    //如果没有,则不需要实现IDisposable!



    public interface ICustom:IDisposable {}
    public class Custom:ICustom {
    public SuperObject Super {get;保护组; }
    $ b $ public Custom(){
    Super = new SuperObject();

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

    公共类Moo:控制器{
    自定义c;

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

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






    $ b

    请注意,如果Super对象没有任何可用资源那么在实现IDisposable和使用Dispose方法方面没有意义。如果海关只有一次性对象是超类对象,那么同样适用于那里,并且同样的逻辑再次到达Moo。最后,如果以上都适用,并且没有其他可用的对象围绕您所需要的全部实际需要:

      public class Moo:控制器{
    自定义c;

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


    public Dispose(){
    base.Dispose();
    }
    }


    I've looked in SO about a question like this one, and even that I've found quite a few, any of those threw any light into this matter for me.

    Let's assume I have this code:

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

    • Do I need the protected virtual void Dispose(bool) on SuperObject? Since there is really nothing to dispose there.

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

    Now what happens if I want/need/try to use Custom on a class like System.Web.Mvc.Controller which already implements and has implemented IDisposable?

    public class Moo : Controller
    {
        Custom c;
    
        public Moo()
        {
            c = new Custom();
        }
    
        // Use c throughout this class        
    }
    

    How to properly dispose c in Moo?

    解决方案

    The normal approach is to apply the standard IDispoable implementation - HOWEVER this is really only necessary if your class or some class that derives from it will use UNmanaged resources - this case is infact VERY rare (and when this case does apply it is better to wrap the unmanaged resource in its own class that has a full standard IDisposable implementation).

    So assuming you are not dealing with UNmanaged resources (raw file handles, globally alloced memeory etc) and are only dealing with members that are disposable (i.e that have managed resources and implement IDisposable) then you can safely get a way with a mimimal implimentation of IDispose - that is:

    Just have a single void Dispose() method. In that method just call dispose on dispoable members and then Dispose on the base class if its disposable. If you have a class hierachy its ok to make this Dispose virtual. There is no need to have a Dispose(bool) method. Nor is there any need to check if the object is disposed - because all your doing is calling dipsose on other objects and those implementation will do that check.

    If you don't like the mimimal appraoch then apply the standard full implimentation (but it is not strictly necessary). I.e either do a standard implimentation because your a stickler for following the recommended approach OR do a simple minimal (but correct) implementation - but don't do something in between (i.e not standard, not simple or not correct)!

    See this question for more details: Minimal IDispose implimenation for managed resources only

    So in your case the following is the mimimal implimentation:

    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();       
        }
    }
    

    Note that if Super object does not have any disposable resources then there is no point in implementing IDisposable and having a Dispose method. If Customs only disposable object is SuperObject then the same applies there, and again the same logic rocks through to Moo. Finally then if all the above applies and there are no other disposable objects around all you need really need is:

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

    这篇关于理解一次性对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆