【发布时间】:2016-06-21 01:59:08
【问题描述】:
MSDN 文档和 StackOverflow 上的许多答案不遗余力地讨论正确实现 IDisposable,例如MSDN IDisposable, MSDN Implementing IDisposable, An excellent StackOverflow Q&A
但是,它们似乎都没有涵盖我拥有的更常见的用例:当我的班级有一个比一种方法寿命更长的IDisposable 成员时该怎么办?例如
class FantasticFileService
{
private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable
public FantasticFileService(string path)
{
fileWatch = new FileSystemWatcher(path);
fileWatch.Changed += OnFileChanged;
}
private void OnFileChanged(object sender, FileSystemEventArgs e)
{
// blah blah
}
}
最接近解决此问题的MSDN 仅涵盖当IDisposable 的实例是短暂存在的用例,例如调用Dispose通过使用using:
仅当您使用非托管资源时才实施 IDisposable 直接地。如果您的应用程序仅使用实现 IDisposable,不提供 IDisposable 实现。相反,你 应该调用对象的 IDisposable.Dispose 实现,当你 用完了。
当然,在我们需要实例比方法调用更长时间的情况下,这是不可能的!?
我怀疑正确的方法是实现IDisposable(将责任传递给我的班级的创建者来处理它)但没有所有终结器和protected virtual void Dispose(bool disposing)逻辑,因为我没有任何未管理的资源,即:
class FantasticFileService : IDisposable
{
private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable
public FantasticFileService(string watch)
{
fileWatch = new FileSystemWatcher(watch);
fileWatch.Changed += OnFileChanged;
}
public void Dispose()
{
fileWatch.Dispose();
}
}
但是为什么任何官方文档都没有明确涵盖这个用例呢?而且它明确说如果你的类没有非托管资源就不要实现IDisposable,这让我犹豫不决......一个糟糕的程序员该怎么做?
【问题讨论】:
-
您的第二个链接Implementing a Dispose Method 解释了他们说“在此处释放任何其他托管对象”。另外我不确定您是否正确实施了
Dispose()。你不缺GC.SuppressFinalize(this);吗? -
“我也不确定你是否正确地实现了 Dispose()”,很有可能!问题是 如何在这种特定场景下正确实施 dispose,我不会问我是否知道!
-
Could not find good link on "yes you should implement IDsiposable in this case",但我没有看到任何其他普遍同意的方式来指定您的对象最后需要显式清理。请注意,除非您的班级是
sealed(stackoverflow.com/questions/3882804/finalizer-and-idisposable),否则您仍然需要使用完整的 Dispose 模式