C# - 处理递归对象

C# - Disposing Recursive Objects

假设我有一些对象 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
    }
}

Should I recursively call their dispose methods

是的。

但仅当 C 实际需要 IDisposable 时,这在您的代码中并不明显。它指的是相同 class 的实例这一事实无关紧要,请对所有拥有的 IDisposable 对象调用 Dispose()。

如果这是对 'help' 垃圾收集器的尝试,请停止它,什么也不做。

Should I recursively call their dispose methods

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

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

不仅是正确答案。

您要问的主要问题 - LIST 的容器是真实的并且其中的项目是单一所有者吗?

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

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

在 C++ 中的 shared_ptr 或 .NET 中的常用引用中,共享的忍者方式在哪里 - 跟踪使用计数 -

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

但希望这不是你的情况)