2013-09-29 55 views
2

我看着在SO大约像这样的问题,甚至我发现相当多的,任何那些扔任何光线进入这件事情对我来说。了解一次性对象

假设我有这样的代码:

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

    protected virtual void Dispose(bool disposing) { } 
} 
  • 我需要在SuperObjectprotected 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   
} 

如何妥善处理在Mooc

+2

当没有什么可配置的时候,请不要实施IDisposable。 –

+0

为什么当你没有Finaizer时使用'GC.SuppressFinalize()'? –

+0

@HamletHakobyan这是一个很好的问题,也许你可以在这里帮忙:http://stackoverflow.com/q/19078536/544283。 – Esteban

回答

6

正常的方法是应用standard IDispoable implementation - 但是,如果你的类或某些类派生自它将使用非托管资源,这确实是只需要 - 这种情况下是INFACT非常罕见(当这种情况确实应用最好将非托管资源包装在自己的具有完整标准IDisposable实现的类中)。所以假设你没有处理非托管资源(原始文件句柄,全局分配memeory等),只处理一次性成员(即已管理资源并实现IDisposable)的成员,那么你可以安全地获得IDispose的mimimal执行力度 - 是:

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

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

详情请参见这个问题:Minimal IDispose implimenation for managed resources only

所以你的情况,以下是mimimal执行力度:

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

注意,如果超级对象没有任何可支配资源,那么就没有一点在实现IDisposable和有一个Dispose方法。如果海关只有一次性对象是超类对象,那么同样适用于那里,并且同样的逻辑再次到达Moo。最后,如果以上全部适用,并且没有其他一次性物体围绕您所需要的全部真正需要:

public class Moo : Controller { 
     Custom c; 

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

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

此处提供“标准IDispoable实现”链接的更新文档:https://msdn.microsoft.com/en-us/library/fs2xkftw(v=vs.110).aspx –

2

如何正确处理cMoo

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逻辑。只进行一次配置是一个好主意,您可能想要在处理后捕获使用情况。
  • 省略析构函数(终结)本身就是一种很好的想法,但你现在有没有派生类应该拥有一个非托管资源额外的约束。