在IDisposable类层次结构中正确处理ObjectDisposedException异常 [英] Handling ObjectDisposedException correctly in an IDisposable class hierarchy

查看:143
本文介绍了在IDisposable类层次结构中正确处理ObjectDisposedException异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这对单个类来说可以正常工作。但是,当您从一次性资源中进行子类化,并且子类包含其本身的本机资源和独特方法时,事情会变得有点棘手。大多数示例显示如何正确地覆盖 Dipose(bool disposal),但不要超出这一点来处理 ObjectDisposedException 。 / p>

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






首先:



子类和基类都需要能够跟踪处理的状态。有一些主要的选择我知道 -




  • 1)声明私人bool处置;在两个班。每个类跟踪自己的这个不适用,并根据需要抛出。


  • 2)使用protected bool Disposed {get;私人集合}而不是一个字段。 3)提供一些受保护的帮助方法来检查处理状态,并通过拉动当前类型的名称来扔出来。反映如果对象被处理。




通过选项看到的缺点的优点是:




  • 1)这个闻起来,因为它包含重复的布尔,但似乎工作正常。我经常在使用其他代码时使用此功能。


  • 2)这将重复布尔值,但不是设计指南书籍的写法等。这是我通常使用的,因为它保持一个单一的状态。


  • 3)这似乎是对我最干净的选择,但没有不会出现在标准指南中。与课堂用户的其他方式相比,可能稍微少一点。




或者另一个,尝试使用所有这三种方法。我想知道三种方法的优点和缺点,以及任何其他想法,以便更清洁,更好的处理方法。在处理这个问题上你会有什么选择,为什么?






第二:



抛出 ObjectDisposedException 时,你为name参数使用什么?我知道典型方法调用是:



 
throw new ObjectDisposedException(GetType() );



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



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



我不认为这是一个好主意 - 但是我碰到了一些由别人写的代码。通过实现方法返回的类的名称是否有优点或缺点?

解决方案

我通常实现第一个选项。实际上,这似乎是设计指南推荐的。原因并不明显,但我认为这是一个很好的例子:任何一个类的实施者都应该拥有同样的保护措施,以防止对象作为普通消费者被处置。换句话说,最好不要假设,正在实现派生类的人精确地知道他们何时可以调用某种方法,其成功的执行可能取决于或者不取决于对象是否已被处置或对于你的第二个问题,我将再次坚持通过的推荐做法,而不是(尽管理想情况下,应该通过XML注释来记录)



GetType()。FullName ,特别是因为它在核心.NET框架中使用。即使您认为替代方法更适合,我认为最好坚持.NET框架中使用的方法,以保持一致性。



总结如下:as有了所有的指导方针,显然你要如何实现某个设计功能,除非你有一个非常好的理由,只要坚持下去,这是非常有意义的。在这两种情况下,只要使用一贯且最好记录在用户身上,就可能不会对您使用的某些替代方案造成很大的伤害。


When implementing IDisposable correctly, most implementations, including the framework guidelines, suggest including a private bool disposed; member in order to safely allow multiple calls to Dispose(), Dispose(bool) as well as to throw ObjectDisposedException when appropriate.

This works fine for a single class. However, when you subclass from your disposable resource, and a subclass contains its own native resources and unique methods, things get a little bit tricky. Most samples show how to override Dipose(bool disposing) correctly, but do not go beyond that to handling ObjectDisposedException.

There are two questions that I have in this situation.


First:

The subclass and the base class both need to be able to track the state of disposal. There are a couple of main options I know of -

  • 1) Declare private bool disposed; in both classes. Each class tracks its own this.disposed, and throws as needed.

  • 2) Use protected bool Disposed { get; private set; } instead of a field. This would let the subclass check the disposed state.

  • 3) Provide some protected helper method to check the disposed state, and throw by pulling the current type name via reflection if the object is disposed.

The advantages as disadvantages I see to each by option are:

  • 1) This "smells" to me since it contains duplicated booleans, but seems to work fine. I often use this when subclassing other code.

  • 2) This takes out the duplicated booleans, but is not the way the design guidelines books are written, etc. This is what I typically use, though, since it keeps it a single point for state.

  • 3) This seems like the cleanest option to me, but doesn't appear in standard guidelines. It may be a little less expected of an approach than others from users of the class.

I, at one point or another, have tried using all three of these approaches. I would like to know advantages and disadvantages to the three approaches, as well as any other ideas for a cleaner, better way to handle this. What choice would you make in handling this, and why?


Second:

When throwing the ObjectDisposedException, what do you use for the name argument? I know the "typical" method call is:

throw new ObjectDisposedException(GetType().FullName);

There is a comment on this page from a Microsoft employee suggesting that implementing the concrete class's full name is the appropriate usage.

In the third option above, this would be the only meaningful choice. However, if the class implements the throwing itself, you could potentially return the name of the class that defines the method that was called. (ie: the base class could return the base class's name, not the concrete subclass)

I don't think this is a good idea - but I ran into this on some code written by somebody else. Are there advantages or disadvantages to having the name of the class implementing the method returned?

解决方案

I typically implement the first option. Indeed, it seems to be what the design guidelines recommend. The reason isn't immediately apparent, but I consider it a good one nonetheless: any implementer of the class should have the same sort of protection against the case where the object is disposed as general consumers. In other words, it's best not to assume that whoever is implementing a derived class knows precisely when they can call a certain method, whose successful execution may or may not depend on whether the object has already been disposed or not (though ideally this should be documented via XML comments anyway).

Regarding your second question, I would again stick with the recommended practice of passing GetType().FullName, especially since it's used in the core .NET framework. Even if you think alternative methods are more appropiate, I think it's best to stick to the method used in the .NET framework for the sake of consistency.

To conclude: as with all guidelines, it's clearly up to you how you want to implement a certain design feature, though unless you have a particularly good reason it's highly advisable just to stick with them. In both these situations, it probably wouldn't do a great deal of harm to utilise some of the alternatives you suggested in your post, so long as they are used consistently and preferably documented to the user.

这篇关于在IDisposable类层次结构中正确处理ObjectDisposedException异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆