当正确实现 IDisposable 时,大多数实现(包括框架指南)建议包括 private bool disposed; 成员以安全地允许多次调用 Dispose(), Dispose(bool) 以及扔 对象处置异常 在适当的时候。

这对于单个类来说效果很好。但是,当您从一次性资源进行子类化并且子类包含其自己的本机资源和独特方法时,事情会变得有点棘手。大多数示例展示了如何覆盖 Dipose(bool disposing) 正确,但不要超出处理范围 ObjectDisposedException.

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


第一的:

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

  • 1)声明私有bool已处置;在两个班级中。每个类都会跟踪自己的 this.dispose,并根据需要抛出。

  • 2)使用 protected bool Dispose { get;私人套装;} 而不是一个字段。这将使子类检查已处置状态。

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

我认为每个选项的优点和缺点是:

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

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

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

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


第二:

当投掷时 ObjectDisposedException, ,你用什么来作为名称参数?我知道“典型”方法调用是:

throw new ObjectDisposedException(GetType().FullName);

有一条评论 在本页 一位 Microsoft 员工建议实现具体类的全名是正确的用法。

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

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

有帮助吗?

解决方案

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

关于你的第二个问题,我会再次坚持推荐的通过做法 GetType().FullName, ,特别是因为它用于核心 .NET 框架。即使您认为其他方法更合适,我认为为了保持一致性,最好坚持使用 .NET 框架中使用的方法。

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

其他提示

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

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

使用 protected bool Dispose { get;私人套装;} 而不是一个字段。这将使子类检查已处置状态。

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top