12

在正确实现 IDisposable 时,包括框架指南在内的大多数实现都建议包含一个private bool disposed;成员,以便安全地允许多次调用Dispose(),并在适当时Dispose(bool)抛出ObjectDisposedException 。

这适用于单个类。但是,当您从一次性资源中进行子类化,并且子类包含自己的本机资源和独特的方法时,事情会变得有些棘手。大多数示例显示如何Dipose(bool disposing)正确覆盖,但不要超出处理ObjectDisposedException

在这种情况下,我有两个问题。


第一的:

子类和基类都需要能够跟踪处置状态。我知道有几个主要选项 -

  • 1) 声明 private bool 已处理;在两个班级。每个类都跟踪自己的 this.disposed,并根据需要抛出。

  • 2) 使用受保护的 bool Disposed { get; 私人套装;} 而不是一个字段。这将让子类检查处置状态。

  • 3) 提供一些受保护的辅助方法来检查已释放状态,如果对象已释放,则通过反射拉出当前类型名称来抛出。

我看到的每个选项的优点和缺点是:

  • 1)这对我来说“闻起来”,因为它包含重复的布尔值,但似乎工作正常。在子类化其他代码时,我经常使用它。

  • 2)这取出了重复的布尔值,但不是设计指南书籍的编写方式,等等。不过,这是我通常使用的,因为它保持它的单点状态。

  • 3)这对我来说似乎是最干净的选择,但没有出现在标准指南中。与班级用户的其他方法相比,这种方法的期望可能会少一些。

我曾经尝试过使用所有这三种方法。我想知道这三种方法的优缺点,以及任何其他更清洁、更好的处理方法的想法。在处理这个问题时你会做出什么选择,为什么?


第二:

抛出时ObjectDisposedException,你用什么来做 name 参数?我知道“典型”的方法调用是:

throw new ObjectDisposedException(GetType().FullName);

Microsoft 员工在此页面上有一条评论,建议实现具体类的全名是适当的用法。

在上面的第三个选项中,这将是唯一有意义的选择。但是,如果该类自己实现了抛出,您可能会返回定义所调用方法的类的名称。(即:基类可以返回基类的名称,而不是具体的子类)

我认为这不是一个好主意 - 但我在其他人编写的一些代码上遇到了这个问题。返回实现方法的类的名称有优点还是缺点?

4

3 回答 3

5

我通常实现第一个选项。事实上,这似乎是设计指南所建议的。原因不是很明显,但我仍然认为这是一个很好的原因:该类的任何实现者都应该对对象作为一般消费者处理的情况具有相同的保护。换句话说,最好不要假设任何实现派生类的人都知道他们何时可以调用某个方法,其成功执行可能取决于对象是否已经被释放(尽管理想情况下这应该是无论如何通过 XML 注释记录)。

关于您的第二个问题,我将再次坚持建议的传递做法GetType().FullName,特别是因为它用于核心 .NET 框架中。即使您认为替代方法更合适,我认为最好还是坚持使用 .NET 框架中使用的方法,以保持一致性。

总结:与所有指南一样,您希望如何实现某个设计功能显然取决于您,但除非您有特别好的理由,否则强烈建议您坚持使用它们。在这两种情况下,使用您在帖子中建议的一些替代方案可能不会造成太大的伤害,只要它们始终如一地使用并且最好记录给用户。

于 2009-03-21T00:27:58.093 回答
2

声明私有 bool 已处理;在两个班级。每个类都跟踪自己的 this.disposed,并根据需要抛出。

当您无法修改基类时,这是实用的解决方案。

使用受保护的 bool Disposed { get; 私人套装;} 而不是一个字段。这将让子类检查处置状态。

为什么不将其公开并称为 IsDisposed 呢?然后您将执行与 System.Windows.Forms.Control 相同的操作。当您可以修改基类时,这是一个很好的解决方案。

您可能会返回定义该方法的类的名称

不,您引用的示例代码使用了“GetType().FullName”。这始终是最派生类型的名称,而不是实现特定方法的类型。

于 2009-03-21T00:29:58.150 回答
0

我的倾向是让基类声明一个整数 IsDisposed 标志,然后让外部“Dispose()”方法互锁。在开始处理之前将其交换为“1”(如果在交换之前它不为零,请跳过处置)。要支持 Finalize,事情需要稍微复杂一些,但是实现 Finalize 的类不应该从 Object 以外的类派生,并且 - 除了像 SafeHandle 这样的专用或实用类 - 不应该继承自。

于 2011-04-16T20:01:31.023 回答