C# - 处理递归对象

时间:2015-11-10 18:56:04

标签: c# garbage-collection idisposable

假设我有一些对象C,它包含对自身实例的引用,并且还实现了IDisposable。如何处理对C的其他实例的引用?我应该递归调用他们的dispose方法,还是应该将它们设置为null?换句话说,首选哪种型号?

模型1:递归处置

public class C : IDisposable
{
    public List<C> subItems = new List<C>();

    public void Dispose() 
    {
        foreach (C subItem in subItems)
            subItem.Dispose();
        // Dispose other stuff
    }
}

模型2 :设置等于null

public class C : IDisposable
{
    public List<C> subItems = new List<C>();

    public void Dispose() 
    {
        subItems = null;

        // Dispose other stuff
    }
}

3 个答案:

答案 0 :(得分:8)

  

我应该递归调用他们的处理方法

但只有当C实际上需要IDisposable时,这在您的代码中并不明显。它引用同一个类的实例的事实是不相关的,在所有拥有的IDisposable对象上调用Dispose()。

如果这是尝试帮助&#39;垃圾收集器,然后停止它,什么都不做。

答案 1 :(得分:-1)

  

我应该递归调用他们的处理方法

没有。如果你不需要它。 (GC清理它)

是。如果对象使用非托管资源。不处理非托管资源会导致内存泄漏。

答案 2 :(得分:-1)

这不仅是正确答案。

你要问ASK的主要问题是LIST真实的还是单个OWNER项目的主要问题吗?

如果是 - 唯一有效的行为 - 显式调用Dispose(如在第一个伪代码中)

如果项目是或可以共享,并且可以在另一个上下文而不是单个容器中使用(例如,与StreamWriter和Stream一起使用 - StreamWriter可以是&#34;所有者&#34; of Stream并关闭它,但是您可以使用keepLive参数来保持Stream打开)。在共享的情况下,唯一有效的方法是从这种情况运行 - 因为如果你处置 - 你可以打破其他任务,如果不处理,只是清除列表 - 你可以保留一些资源,没有任何机会清理。

在C ++中的shared_ptr或.NET中的常用引用中使用ninja方式共享的方式 - 跟踪使用计数 -

class C:IDisposable{
    int usageCount = 0;
    public void AddUsage(){usageCount++;}; 
    public void Dispose(){
         if(usageCount>0){
            usageCount--;
            return;
         }
         //ELSE DO REAL DISPOSE LOGIC
    }
 }

但希望不是你的情况)