7

在一个实现的类中IDisposable,何时检查对象是否已被释放并抛出ObjectDisposedException是否是合理的?在所有公共方法和属性中(除了Dispose)?有时?绝不?

4

5 回答 5

4

您应该仅在不适用于已处置对象的方法中实现该检查。

例如:
如果您的类关闭了 中的数据库连接或文件句柄Dispose,则所有需要这些数据库连接或文件句柄的方法都需要检查实例是否已经公开。

于 2011-05-27T09:44:01.807 回答
2

唯一真正指定的是它public void Dispose()本身不应该抛出任何东西。

任何需要(非)托管资源的方法都应该抛出。

在我看来,这只剩下几个有争议的案例:

  • IsOpen,IsDisposed:我不会扔
  • 其他 IsSomeStatus:视情况而定。
  • 长度,计数,位置:我认为封闭的流没有长度,所以抛出

当类组合(不相关的)函数(如 Stream和Collection )时,它变得更加困难。我们只是不应该那样做。

于 2011-05-27T10:03:11.630 回答
2

如果一个对象支持 IsDisposed,则该方法本身不应该抛出;如果 IsDisposed 返回 true,则许多其他方法都应该抛出异常,但异常应该由这些方法生成,而不是由 IsDisposed 生成。一个人可能有一个实用方法 AssertNotDisposed 如果一个对象被释放,它会抛出,但这种行为应该来自具有该名称的方法。

否则,我建议在很多情况下,让一个对象持有 IDisposable 对象,并且能够在保持有用状态的同时处理内部对象。例如,一个对象的功能是显示和维护一个无模式对话框以从用户那里获取信息,即使在对话框关闭后,它也可能有用地保留字段内容的副本。这样的对象应该提供一个“关闭”方法,该方法将处理内部的 Disposable 对象但保持有用的状态。虽然它也可以有一个 Dispose 方法,该方法会调用 Close,但也会设置一个“NoLongerValid”标志,该标志会导致字段属性抛出,但我认为这不会真正增加任何价值。

我承认,很多情况下,一个对象在被处理后可以保持有用状态,这表明一个可能应该被拆分的类。例如,Font 类可能应该被拆分为一个非一次性 FontInfo 类(保存字体的描述,但不包含 GDI 句柄)和一个 IDisposable ReadyFont 类(继承 FontInfo,并封装 GDI 字体对象)。使用字体的例程可以检查给定的对象是 FontInfo 还是 ReadyFont;在前一种情况下,他们可以创建 GDI 字体,使用它,然后发布它;在后一种情况下,他们可以使用 ReadyFont 的 GDI 字体对象并释放它。ReadyFont 的创建者将负责确保其清理。

事实上,我不知道系统在呈现控件时是否会尝试使用与控件的 Font 属性关联的 GDI 对象,但我知道如果 Font 被 Disposed(即使它之前 Disposed将其分配给 Font 属性!)。如果需要,控件当然可以创建新的 GDI 字体;我不知道他们是否总是创建一种新的 GDI 字体,或者他们是否只在旧字体被处理后才这样做。前一种行为似乎更高效,但除非仔细编码,否则如果一个线程试图在另一个线程使用字体时释放字体,则可能会导致问题。

于 2011-05-27T14:35:41.220 回答
1

正如您所说,我将在除 Dispose 和 IsDisposed 之外的所有公共方法和属性中实现此检查。这是一种标准模式,可防止开发人员误以为它仍然有效而使用您的类型。

于 2011-05-27T09:52:26.703 回答
1

使用已处置的对象是您希望尽快找到的编程错误。

检查的地方越多,您发现错误的速度就越快。
您绝对应该检查它在哪里处置的对象会导致某种其他类型的异常(即空指针)不会使用户感到困惑。

在其他地方,这取决于应用程序是否值得付出努力。

于 2011-05-27T10:03:39.203 回答