IsDisposed如何真正起作用?

时间:2013-12-11 06:42:19

标签: c# .net garbage-collection clr idisposable

有很多博客,SO问题告诉你如何知道对象是否已被处置。例如。使用某些类可用的IsDisposed属性。

我想知道:

  • 假设IsDisposed正在返回true,如果对象已经处理好,我们怎么可以在其上调用IsDisposed属性?
  • 如果我们可以访问其属性,我们怎么能说对象已经死亡或丢弃或处置? (您是不是通过调用其属性来引用它?!)

更新#1:

我在几个答案之后跟进了问题,说明" Disposed并不意味着对象已经死亡;它只是意味着它所持有的任何未经纳入的资源都被释放了。":

  • 这是否意味着Disposed并未说this对象已被处理?
  • 如果Disposed对象本身没有死,为什么我们会ObjectDisposedException? (这不是说这个物体不能再使用了吗?)

3 个答案:

答案 0 :(得分:5)

“Disposed”只是说“IDisposable.Dispose”已被调用的简写。这通常(但不是唯一地)用于表示它已经释放了它可能持有的任何非托管资源。

它与垃圾收集无关,并不意味着该对象“死”或“被扔掉”。

<强>更新

  

这是否意味着Disposed不是说这个对象被处理了?

不,这意味着它被处置掉了,即它已经释放了它的非托管资源。

  

如果Disposed对象本身没有死,为什么我们会得到ObjectDisposedException? (这不是说这个物体不能再使用了吗?)

由每个类型决定何时抛出ObjectDisposedException。但是,当您尝试访问需要已释放的非托管资源的成员时,通常会抛出它。在处理对象后,每个成员访问都会引发ObjectDisposedException,这通常不正确。

举一个简单的例子,如果你有FileStream被处置(即文件被关闭):

  • 尝试拨打ReadByte会抛出ObjectDisposedException,因为您无法从未打开的文件中读取。

  • 但您仍然可以访问Name属性,该属性提供传递给FileStream构造函数的名称,并且不需要访问非托管资源(基础文件)

答案 1 :(得分:1)

IDisposable的目的是明确请求在销毁父对象之前销毁非托管资源(以及实现IDisposable的托管资源)。这样可以从垃圾收集的角度节省资源。

因此,IsDisposed将一直存在,直到对象的生命周期结束。

答案 2 :(得分:1)

.NET和Java框架都保证绝对,积极,无任何例外,每个对象及其所有字段都将继续存在,只要可以从任何地方检索对它的任何类型的引用在宇宙中(即它“可达”)。如果对象的唯一可到达引用保存在WeakReference对象中,则垃圾收集器将销毁这些引用(因此,任何地方都不再有任何类型的可访问引用,使对象有资格进行收集)。已注册终结器/析构函数的对象通过让系统保留所有这些对象的列表来处理;在将这些对象从该列表中删除之前,不能销毁这些对象。

实现IDisposable的对象遵循上述规则的方式与任何其他对象相同。使这些对象“特殊”的原因在于,它们中的许多将在某些方法中(可能包括它们的构造函数)要求其他实体代表它们做某事(可能对其他实体造成损害),直到另行通知为止;当调用其他方法(包括但不限于Dispose)时,他们会发出通知。例如,封装文件的对象可能会要求操作系统对文件进行独占访问,从而锁定可能想要使用它的任何其他人,并且可能会通知操作系统Dispose时不再需要这样的访问权限。或Close被召唤。通常,对象要求实体代表他们行动,因为需要来自这些实体的帮助来实现他们的方法(例如,对象将无法执行“从文件读取数据”操作,除非它已被授予对相关文件的访问权限)。一旦外部实体被告知不再需要他们的服务,那么需要这些服务的方法将无法正常运行。

如果一个方法无法执行其职责,因为它已经释放了它的资源(告诉外部实体不再需要它们的服务)以响应Dispose调用,它是唯一被接受的方式来表明该事实是通过ObjectDisposedException。此外,如果特定方法有时能够在没有现在不可用的外部帮助的情况下执行其职责而有时不能执行其职责,通常认为始终抛出ObjectDisposedException而不是间歇性抛出它更好。但是,如果不希望特定方法或财产实际上利用外部资源,那么一种方法通常可以忽略这些资源是否仍然可用的问题,特别是如果有任何合理的理由,有人可能想在已处置的实例上使用该方法或属性(最明显的例子是IsDisposed属性)。