我应该在分配新对象之前处理旧对象吗?

Car*_*ine 5 c# idisposable

假设我们有两个类Foo和Bar,如下所示。

public class Foo
{
    public static Bar BarInstance { get; set; }

    public static void Main()
    {
        AssignBar("A");
        AssignBar("B");
    }

    private static void AssignBar(string name)
    {
        BarInstance = new Bar(name);
    }
}

public class Bar : IDisposable
{
    public Bar(string name)
    {
        Name = name;
    }
    public string Name { get; set; }
    protected virtual void Dispose(bool disposing)
    {
        if (!disposing)
        {
            return;
        }
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

当对象 A 被对象 B 替换时。我期望Dispose调用,因为由于不再存在对对象 A 的引用,但它不会被调用。您能解释一下原因吗?

CurrentBar.Dispose如果我想要对象 A 被处理,我最终应该像下面那样做吗?

    private static void AssignBar(string name)
    {
        if (BarInstance != null)
        {
         BarInstance.Dispose();   
        }
        BarInstance = new Bar(name);
    }
Run Code Online (Sandbox Code Playgroud)

ang*_*son 4

这取决于所有权。

是Bar给与现在拥有的Foo暗示吗?Foo Bar

如果是这样,那么是的,您应该Dispose在分配新实例之前调用旧实例。

暗示Bar它Foo更像是一笔贷款,即。你可以引用和使用这个对象,但它被其他东西拥有?

如果是这样,那么不,您不应该Dispose在分配新实例之前调用旧实例。


您的代码在这一点上并不完全清楚,我建议您清理它,以便将来更容易推理这种类型。

在我看来,您有以下三种可能情况之一:

  1. Foo永远拥有Bar。在这种情况下,我会将旧实例的处理放在属性的 setter 中,或者如果将新实例放入其中的唯一方法Bar是通过您声明的方法,则完全删除公共 setter。
  2. Foo从未拥有过Bar。在这种情况下,我不会添加任何处理旧实例的代码,但随后我质疑该方法的存在。在这种情况下,很可能没有人真正拥有新建的实例。
  3. Foo只拥有Bar通过您的方法创建的实例,但不拥有通过公共 setter 赋予它的实例。在这种情况下,我将添加一个新字段来跟踪是否Foo拥有,并在方法中将Bar其设置为,并在属性设置器中清除它。true

Dispose无论如何都没有特殊之处,从 C# 的角度来看,它只是另一种方法,因此没有任何自动方法会调用此方法。

但是,如果对象引用非托管资源,则当该对象在某个时刻符合收集条件时,将执行其终结器来释放这些非托管资源。然而,当您知道不再需要它们时,要确定地释放它们,您需要调用Dispose.