【问题标题】:Why can you still use a disposed object?为什么您仍然可以使用已处置的对象?
【发布时间】:2016-03-06 09:38:30
【问题描述】:

我正在努力理解对象的处理和垃圾收集。特别是,我不明白为什么我仍然可以使用已处置的对象。我并没有尝试做任何实际的事情,我现在只是在玩理论,根据我的理解,我认为我无法做到以下几点:

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        using (p)
        {
            p.Name = "I am Name";
        }
        Console.WriteLine(p.Name); // I thought this would break because I've already disposed of p
        Console.ReadLine();
    }
}
public class Person : IDisposable
{
    public string Name;
    public void Dispose()
    {
        Console.WriteLine("I got killed...");
    }
}

我希望有人可以在这里给我一些方向或指导,以消除我对这个概念的误解?

【问题讨论】:

  • 使用using 的常规方式是(using p = new Person()){ ... }。这样一来,您就不必担心一次性用品。
  • @shay__: 是的 - 因为通常有包装类也会处理它们包装的内容,例如带有流和StreamWriter。此外,有时您确实想在之后访问已处置的对象。我认为这是一个完全合理的问题。
  • @JonSkeet 非常感谢!我认为这消除了我在这里的误解。我一直认为该对象被 Dispose() 破坏了,但这只是我摆脱 CLR 不会为我摆脱的非托管资源的机会,然后我可以用托管的东西做我想做的事,直到不再GC 会在什么时候为我解决这个问题?我在想 Dispose() 方法做了一些神奇的事情,这让我对我正在尝试的事情感到困惑。再次感谢!

标签: c# oop


【解决方案1】:

处理一个对象并没有什么神奇的作用——CLR 根本不关心IDisposable...它只是一个在 C#(和其他语言)中支持的框架接口。调用Dispose 就像调用其他方法一样。

如果您没有使一个已处置的对象在您对其执行进一步操作时失败,那么它不会。确实,在某些情况下您真的希望能够 - 例如,在 MemoryStream 上调用 ToArray 在处理后就可以了,即使您不能调用 Read 等. 这在对MemoryStream 的写入被链接到包装器的情况下非常方便,该包装器将处理MemoryStream,但您需要之后的数据。

不过,一般来说,您应该编写代码就好像您不能在处置后使用已处置的对象,除非您确定它仍然支持您需要的操作。 “我希望它会坏...”的默认位置是安全的。

【讨论】:

  • 请注意,.Net 提供了ObjectDisposedException 类,如果在处理后调用类中的方法,您可以抛出该类。一些一次性类会跟踪它们是否已被丢弃,如果您之后尝试使用它们,则抛出 ObjectDisposedException - 但其他一次性类不会。
【解决方案2】:

Dispose 模式用于当您有一个使用非托管资源的对象需要在不再需要时将其释放。托管资源由 GC 自动释放。

在您的示例中,字符串 Name 是托管资源。如果您在那里有一个打开的文件,那将是一个非托管资源。然后,Dispose 方法将关心关闭文件句柄,这将使对象的文件访问在 Dispose 之后不可用。但是,您仍然可以要求提供名称,因为在 GC 收集该对象之前,它会存在。

推荐阅读:MSDN Dispose Pattern

【讨论】:

    【解决方案3】:

    IDisposable 是在托管代码中处理非托管资源的约定。

    您正在实现IDisposable 接口,稍后您只是在进行Dispose() 方法调用,而不是破坏或杀死实际对象

    什么是非托管资源?

    非托管资源是垃圾收集器无法收集的资源。例如,由托管代码之外的其他程序或代码分配的内存。所以GC不能自动管理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 1970-01-01
      • 2013-10-11
      • 2011-04-05
      相关资源
      最近更新 更多