1

我的项目有许多读者和作家类。我开始实现 IDisposable,但我相信它为我的类添加了许多样板代码。对于每个类,我需要实现:

  • 一个析构函数。
  • 一个 Dispose() 方法。
  • 一个 Dispose(bool disposing) 方法。
  • “布尔处理”字段。
  • 检查对象是否已在每个公共方法上释放。
  • 文档(因为我启用了文档标志,否则编译器会发出警告)。

我的问题:

是否值得实施 IDisposable?以前,我使用我的课程,例如:

using (Stream s = File.OpenRead("myfile.bin"))
    x = new SomethingReader(s).ReadSomething();

使用 IDisposable,它并没有太大改善:

using (SomethingReader r = new SomethingReader(File.OpenRead("myfile.bin")))
    x = r.ReadSomething();

我可以只实现 Dispose() 方法吗?

我的班级不使用非托管资源,因此 Dispose(false) 什么也不做。由于我正在清理的也是 IDisposable,因此在处理对象后调用我的方法应该抛出 ObjectDisposedException,因为我正在使用已经处理的对象。

如果您建议实施完整的 IDisposable 模式,有没有办法减少样板代码?

编辑:由于一些答案建议密封课程,我可以确认,事实上,密封课程没有任何问题。

4

4 回答 4

2

如果您没有直接持有非托管资源(即,即使 SafeHandle 也没有直接持有它们),那么通常:

  • 不要实现终结器
  • 不要实现 Dispose(bool)
  • 务必将您的班级标记为已密封。

很遗憾,多年来所有广泛分发的 IDispose 文档都是为编写互操作库的人(即 .NET 框架作者自己)而设计的,而完全忽略了其他所有人更常见的使用模式。

情况有所改善,现在 fxcop(VS 代码分析)为密封类型识别出更轻量级的模式:http: //msdn.microsoft.com/en-us/library/ms244737%28VS.80%29.aspx

于 2010-07-30T15:14:39.390 回答
1

如果您不使用非托管资源,则无需实现完整模式。然而,这种模式有一个侧面的好处。如果有人想扩展您的类,他们可以覆盖Dispose(bool)然后调用base.Dispose(true)以确保所有资源都已处理。

于 2010-07-30T15:06:00.920 回答
0

假设您不需要不同的基类,您可以从Component继承。但是,如果您没有做任何特别的事情,您可以使用该Dispose方法。正如ChaosPandion指出的那样,这可能会导致问题,因为其他人稍后会尝试扩展您的类,因此您可能想要密封您的实现。

于 2010-07-30T15:15:03.517 回答
0

如果有人试图通过覆盖 Dispose(boolean) 来扩展类,而你还没有实现它,那将会失败。但是如果他们尝试覆盖 Dispose(),那将起作用。如果不希望后代类直接控制任何非托管资源,我认为没有任何理由需要密封该类。

于 2010-07-30T16:24:36.473 回答