C# 在 .NET 中覆盖 Dispose(bool disposing) 有什么意义?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/584549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the point of overriding Dispose(bool disposing) in .NET?
提问by Mark Carpenter
If I write a class in C# that implements IDisposable, why isn't is sufficient for me to simply implement
如果我在 C# 中编写一个实现 IDisposable 的类,为什么对我来说简单地实现还不够
public void Dispose(){ ... }
to handle freeing any unmanaged resources?
处理释放任何非托管资源?
Is
是
protected virtual void Dispose(bool disposing){ ... }
always necessary, sometimes necessary, or something else altogether?
总是必要的,有时是必要的,还是其他什么?
采纳答案by Hamish Smith
It's not strictly necessary. It is part of the recommended Disposable pattern. If you haven't read the Framework Design Guidelines section on this (9.3 in the first edition, don't have the second edition handy sorry) then you should. Try this link.
这不是绝对必要的。它是推荐的一次性模式的一部分。如果您还没有阅读关于此的框架设计指南部分(第一版中的 9.3,抱歉没有第二版),那么您应该阅读。试试这个链接。
It's useful for distinguishing between disposable cleanup and finalizable garbage-collection-is-trashing-me.
它有助于区分一次性清理和可终结的垃圾收集正在清理我。
You don't have to do it that way but you should read up on it and understand why this is recommended before discounting it as unnecessary.
您不必这样做,但您应该阅读它并了解为什么建议这样做,然后再将其视为不必要的折扣。
回答by Bob
The additional method with the bool disposing came out of a framework design guideline somewhere. It is simply a pattern to allow your class to have the dispose method be able to be called multiple times without throwing an exception. It isn't absolutely needed. Technically you could do it in the dispose method.
带有 bool 处理的附加方法来自某处的框架设计指南。它只是一种模式,允许您的类可以多次调用 dispose 方法而不会引发异常。它不是绝对需要的。从技术上讲,您可以在 dispose 方法中执行此操作。
回答by Hans Passant
There's a bit of bias in the MSFT docs about the disposable pattern. There are two reasons you should implement IDisposable:
MSFT 文档中对一次性模式存在一些偏见。您应该实施 IDisposable 有两个原因:
- You've got fields of a type that implements IDisposable
- You've got a finalizer.
- 你有一个实现 IDisposable 的类型的字段
- 你有一个终结者。
Case 1 is pretty common in most code. Case 2 is pretty common in code that Microsoft writes, they were the ones that wrote the managed wrappers around the unmanaged resources, the ones that need finalization. But should be very uncommon in your code. After all, you've got all those nice .NET classes to do the dirty work for you. You just have to call their Dispose() methods.
情况 1 在大多数代码中很常见。情况 2 在 Microsoft 编写的代码中很常见,它们是围绕非托管资源编写托管包装器的代码,这些代码需要完成。但是在您的代码中应该很少见。毕竟,您已经拥有所有这些不错的 .NET 类来为您完成繁重的工作。你只需要调用他们的 Dispose() 方法。
Only case 2 requires the disposable pattern. Microsoft needs to use it a lot. You'll just need the simple Dispose() most of the time.
只有案例 2 需要一次性模式。微软需要大量使用它。大多数情况下,您只需要简单的 Dispose()。
回答by Jon Skeet
The full pattern including a finalizer, introduction of a new virtual method and "sealing" of the original dispose method is very general purpose, covering all bases.
包括终结器、新虚拟方法的引入和原始处置方法的“密封”在内的完整模式非常通用,涵盖所有基础。
Unless you have directhandles on unmanaged resources (which should be almostnever) you don't need a finalizer.
除非您直接处理非托管资源(应该几乎从不),否则您不需要终结器。
If you seal your class (and my views on sealing classes wherever possible are probably well known by now - design for inheritance or prohibit it) there's no point in introducing a virtual method.
如果你密封你的类(我对尽可能密封类的看法现在可能是众所周知的 -为继承设计或禁止它),那么引入虚方法就没有意义了。
I can't remember the last time I implemented IDisposable
in a "complicated" way vs doing it in the most obvious way, e.g.
我不记得上次我IDisposable
以“复杂”的方式实现还是以最明显的方式实现,例如
public void Dispose()
{
somethingElse.Dispose();
}
One thing to note is that if you're going for really robust code, you shouldmake sure that you don't try to do anything after you've been disposed, and throw ObjectDisposedException
where appropriate. That's good advice for class libraries which will be used by developers all over the world, but it's a lot of work for very little gain if this is just going to be a class used within your own workspace.
需要注意的一件事是,如果你想要真正健壮的代码,你应该确保在你被处理后不要尝试做任何事情,并ObjectDisposedException
在适当的地方抛出。对于世界各地的开发人员将使用的类库来说,这是一个很好的建议,但是如果这只是在您自己的工作区中使用的类,那么它的工作量很大,收益却微乎其微。
回答by Hosam Aly
In addition to the other great answers, you may want to check these articles:
除了其他很棒的答案之外,您可能还想查看以下文章:
- Implementing IDisposable and the Dispose Pattern Properly
- IDisposable: What Your Mother Never Told You About Resource Deallocation(The Disposable Design Principle)
回答by piers7
Just to expand on what others have said: it's not just that you don't needthe 'complex dispose', it's that you actually don't want it, for performance reasons.
只是为了扩展其他人所说的内容:出于性能原因,您不仅不需要“复杂处理”,而且您实际上不想要它。
If you go the 'complex dispose' route, and implement a finalizer, and then forget to explicitly dispose your object, your object (and anything it references) will survive an extra GC generation before it's really disposed (since it has to hang around one more time for the CLR to call the finalizer). This just causes more memory pressure that you don't need. Additionally, calling the finalizer on a whole heap of objects has a non-trivial cost.
如果你走“复杂处置”路线,并实现一个终结器,然后忘记显式处置你的对象,你的对象(及其引用的任何东西)将在它真正处置之前幸存一次额外的 GC 生成(因为它必须挂在一个CLR 有更多时间调用终结器)。这只会导致您不需要的更多内存压力。此外,在整个对象堆上调用终结器具有非同寻常的成本。
So avoid, unless you (or your derived types) have unmanaged resources.
所以避免,除非你(或你的派生类型)有非托管资源。
Oh, and while we're in the area: methods on your class which handle events from others must be 'safe' in the face of being invoked after your class has been disposed. Simplest is to just perform a no-op if the class is disposed. See http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx
哦,虽然我们在这个领域:处理来自其他人的事件的类上的方法必须是“安全的”,以便在您的类被处理后被调用。最简单的方法是在类被释放时执行无操作。请参阅http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx
回答by kyoryu
One thing that it gives you is the ability to do work in Dispose() unrelated to finalization, and still clean up unmanaged resources.
它为您提供的一件事是能够在与完成无关的 Dispose() 中工作,并且仍然清理非托管资源。
Doing anythingto a managed object other than 'yourself' in a finalizer is extremely... unpredictable. Most of this is due to the fact that your finalizers will be called in stage 2 shutdown of your AppDomain in a non-deterministic manner - so when your finalizer is called, it is extremely likely that objects that you still have references to have already been finalized.
在终结器中对“你自己”以外的托管对象做任何事情都是非常......不可预测的。这主要是因为您的终结器将在 AppDomain 的第 2 阶段关闭时以不确定的方式被调用 - 因此当您的终结器被调用时,您仍然有引用的对象很可能已经被调用敲定。
Dispatching both the Dispose and finalizer calls to the same method allows you to share your shutdown code, while the boolean parameter allows you to skip the managed cleanup if you have any.
将 Dispose 和终结器调用分派到同一方法允许您共享关闭代码,而布尔参数允许您跳过托管清理(如果有)。
Also, the virtual-ness of the method provides an easy way for inheritors to add their own cleanup code, with less of a risk of inadvertently not calling yours.
此外,该方法的虚拟性为继承者添加他们自己的清理代码提供了一种简单的方法,减少了无意中没有调用你的代码的风险。
回答by supercat
If a class implements IDisposable.Dispose()
and a derived class needs to add additional logic, that class must expose some kind of Dispose
method that the derived class can chain to. Since some classes may implement IDisposable.Dispose()
without having a public Dispose()
method, it's useful to have a virtual method which will be protected
in all implementations of IDisposable
regardless of whether they have a public Dispose
method or not. In most cases, the bool
argument isn't really meaningful but should be thought of as a dummy argument to make the protected virtual Dispose(bool)
have a different signature from the may-be-or-maybe-not-public Dispose()
.
如果一个类实现IDisposable.Dispose()
并且派生类需要添加额外的逻辑,则该类必须公开某种Dispose
派生类可以链接到的方法。由于某些类可能在IDisposable.Dispose()
没有公共Dispose()
方法的情况下实现,因此protected
在所有实现中都有一个虚拟方法是有用的IDisposable
,无论它们是否有公共Dispose
方法。在大多数情况下,该bool
参数并没有真正意义,但应被视为一个虚拟参数,以使protected virtual Dispose(bool)
具有与 may-be-or-maybe-not-public 不同的签名Dispose()
。
Classes which doesn't use a protected virtual Dispose(bool)
will require derived classes to handle their cleanup logic in a fashion which differs from the convention. Some languages like C++/CLI which are only equipped to extend IDisposable
implementations which follow that convention may be unable to derive classes from non-standard implementations.
不使用 a 的protected virtual Dispose(bool)
类将需要派生类以不同于约定的方式处理它们的清理逻辑。某些语言(如 C++/CLI)只能扩展IDisposable
遵循该约定的实现,可能无法从非标准实现派生类。