正确实施IDisposable时,大多数实施(包括框架指南)建议包含private bool disposed;
成员,以便安全地允许多次调用Dispose()
,Dispose(bool)
以及抛出{{}适当时{3}}。
这适用于单个班级。但是,当您从可支配资源中继承子类,并且子类包含其自己的本机资源和唯一方法时,事情会变得有点棘手。大多数示例都展示了如何正确覆盖Dipose(bool disposing)
,但不要超越处理ObjectDisposedException
。
在这种情况下我有两个问题。
首先:
子类和基类都需要能够跟踪处置状态。我知道有几个主要选项 -
1)宣布处置私人布尔;在这两个班级。每个类跟踪它自己的this.disposed,并根据需要抛出。
2)使用protected bool Disposed {get;私人集;而不是一个字段。这将让子类检查处置状态。
3)提供一些受保护的辅助方法来检查处理状态,如果对象被处理,则通过反射拉动当前类型名称来抛出。
我看到每个选项的优点是:
1)这个“气味”给我,因为它包含重复的布尔值,但似乎工作正常。我经常在继承其他代码时使用它。
2)这取出了重复的布尔值,但不是设计指南书的编写方式等。这是我通常使用的,因为它使状态保持单点。
3)这对我来说似乎是最干净的选择,但没有出现在标准指南中。对于某种方法而言,它可能比该类用户的其他方法要少一些。
我,曾经尝试过使用这三种方法。我想知道这三种方法的优点和缺点,以及任何其他想法,以更清洁,更好的方式来处理这个问题。你在处理这个问题时会做出什么选择?为什么?
第二
当抛出ObjectDisposedException
时,你对name参数使用了什么?我知道“典型”的方法调用是:
throw new ObjectDisposedException(GetType().FullName);
Microsoft员工发表评论ObjectDisposedException,建议实施具体类的全名是适当的用法。
在上面的第三个选项中,这将是唯一有意义的选择。但是,如果类实现了throw本身,则可能会返回定义被调用方法的类的名称。 (即:基类可以返回基类的名称,而不是具体的子类)
我认为这不是一个好主意 - 但我在其他人编写的代码上遇到了这个问题。使实现方法的类的名称返回有优缺点吗?
答案 0 :(得分:5)
我通常会实施第一个选项。实际上,它似乎是设计指南推荐的内容。原因并不是很明显,但我认为它是一个很好的原因:该类的任何实现者应该具有相同的保护,以防止对象作为一般消费者处置。换句话说,最好不要假设实现派生类的人确切地知道何时可以调用某个方法,其成功执行可能会或可能不会取决于对象是否已被处理或不是(尽管理想情况下这应该通过XML注释来记录)。
关于你的第二个问题,我将再次坚持传递GetType().FullName
的推荐做法,特别是因为它在核心.NET框架中使用。即使您认为替代方法更合适,我认为最好坚持使用.NET框架中使用的方法以保持一致性。
总结:与所有指南一样,显然由您决定如何实现某个设计功能,但除非您有特别好的理由,否则坚持使用它们是非常明智的。在这两种情况下,使用您在帖子中建议的一些替代方案可能不会造成很大的伤害,只要它们被一致地使用并且最好记录给用户。
答案 1 :(得分:2)
声明私人布尔处置;在这两个班级。每个类跟踪它自己的this.disposed,并根据需要抛出。
当您无法修改基类时,这是实用的解决方案。
使用protected bool Disposed {get;私人集;而不是一个字段。这会让子类检查处理状态。
为什么不把它公开并称之为IsDisposed呢?然后你会做与System.Windows.Forms.Control相同的事情。当您可以修改基类时,这是一个很好的解决方案。
您可能会返回定义方法的类的名称
没有。您引用的示例代码使用“GetType()。FullName”。这始终是派生类型最多的名称,而不是实现特定方法的类型。
答案 2 :(得分:0)
我倾向于让基类声明一个整数IsDisposed标志,然后让外部的“Dispose()”方法Interlocked.Exchange在开始处理之前将其更改为“1”(如果它在交换之前不是零,跳过处置)。支持Finalize需要更复杂一些,但实现Finalize的类不应该从Object以外的类派生,并且 - 除了SafeHandle之类的专用或实用类之外 - 不应该继承。< / p>