6

给大家一个问题。

在我的公司,我们正在开发一个在 Microsoft 的 MVC 框架内运行的应用程序。我们正在实现的控制器类继承自MVC 基类 Controller。例子:

public class MyController: Controller
{
    protected bool IsDisposed { get; set; }
… various methods…
 }

我们在团队中的讨论围绕 Dispose() 模式展开。本质上,这涉及实现 IDisposable 接口,最好根据 Microsoft 认可的模式。

例如,请参阅此链接:http: //msdn.microsoft.com/en-us/library/fs2xkftw%28v=vs.110%29.aspx

有趣的是,我们的控制器类不拥有任何资源,无论是托管的还是托管的。这样一来,Dispose(bool) 的实现就大大简化了:

protected override void Dispose(bool disposing)
{
    IsDisposed = true;
    base.Dispose(disposing);
}

关于IsDisposed属性的使用(或需要)存在一些分歧,用于以下方法:

protected void ThrowIfDisposed()
{
    if (IsDisposed) throw new ObjectDisposedException(“MyController”);
}

然后在每个执行“实际”工作的方法开始时调用此方法。这里的想法是不应再次使用已处理的对象,因此它应该抛出 ObjectDisposedException。另一种观点是,由于Dispose(bool)“什么都不做”(除了设置IsDisposed属性和调用Dispose(bool)基类),“已处理”对象并不是真正处于不可用状态,因此没有理由抛出。因此,甚至没有理由实施Dispose(bool).

反对这一点的一个论点是 MyController 应该在它被释放并调用它的一个方法时抛出,以便在将来的版本中添加托管和/或非托管资源时它的行为不会改变。

反对最后一点的论点是 MyController 不应该在将来的版本中添加任何资源,而是应该从将来需要添加资源的情况下派生出来。另一个问题是:为什么(库)类 Controller 不实现ThrowIfDisposed()或类似的东西?

因此,总而言之,派系一想要实施Dispose(bool)ThrowIfDisposed()如上所示,派系二认为它们是不必要的并且想要取消它们。

这两种观点我都看到了优点,我无法真正下定决心。意见?

4

3 回答 3

7

有趣的是,我们的控制器类不拥有任何资源,无论是托管的还是托管的。

那么您不需要 IDisposable 模式。

ThrowIfDisposed()然后在每个执行“实际”工作的方法开始时调用此方法 [ ]。

这里的问题是:为什么?

如果您确实想跟踪可用/废弃状态,那么不要将其称为 IsDisposed。

为什么(库)类 Controller 不实现 ThrowIfDisposed() 或类似的东西?

因为没用。

回到开头:为什么有人认为这是必要的?它是干什么用的?
看来你可以把它撕下来。

于 2014-07-05T07:38:39.013 回答
2

如果对象在处理后收到请求,则请求不应因 -- 以外的任何原因而失败,ObjectDisposedException这意味着它不应导致 a NullReferenceException、产生垃圾数据、使系统崩溃或做任何其他此类事情。这并不意味着请求不应该成功——只是这ObjectDisposedException应该是唯一的失败模式。

至于IsDisposed,在大多数情况下,我真的看不出它有多大用处。不知道对象是否被释放的代码通常不会对对象的状态有足够的了解,无法知道它是否可能由于其他原因而无法使用;因此,不知道一个对象是否被释放的代码通常不应该对它做任何事情,除非——在某些情况下——对它做任何事情,并且在大多数情况下,如果一个对象没有被释放Dispose,你会想要调用它。 Dispose'还没有被处置,一个人应该简单地Dispose无条件地打电话。有一个方法MayNeedDisposing可以返回true具有非平凡Dispose方法的对象,直到它们被释放,但这样的方法可以无条件地返回false具有 null 的对象。Dispose方法[在一个类例如注册一个回调纯粹是为了调用Dispose某物的情况下,MayNeedDisposing预先测试可能是一个有用的优化]。

最后,关于一个类或接口是否应该实现或继承IDisposable,问题不在于类型本身是否获取资​​源,而是对获取资源的某物的最后幸存引用是否可能存储在该类型中。例如,尽管绝大多数IEnumerator<T>实现不获取资源,但有些实现,并且在许多此类情况下,对此类对象的唯一引用将存储在 type 的变量中IEnumerator<T>,由不知道所讨论对象是否存在的代码保存有没有资源。请注意,非泛型IEnumerator不会实现IDisposable,但某些实现会获取资源。因此,调用的代码IEnumerable.GetEnumerator将需要调用Dispose返回的枚举器(如果它实现)IDisposable. IEnumerator不继承的事实IDisposable并不能免除接收同样从调用责任中IEnumerator实现的实现的代码——它只会使此类代码更难履行该责任。IDisposableDispose

于 2014-07-07T17:45:12.250 回答
0

Faction two is absolutely right. Don't do it.

Implementing IDisposable in the way described and for the reasons given is a violation of at least three good principles.

  1. You ain't gonna need it. http://c2.com/cgi/wiki?YouArentGonnaNeedIt
  2. Do the simplest thing that could possibly work. http://www.xprogramming.com/Practices/PracSimplest.html
  3. Keep it simple stupid. https://en.wikipedia.org/wiki/KISS_principle

It's just wrong on every level. Don't do it.

于 2014-07-05T08:33:56.997 回答