C# 完成与处置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/732864/
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
Finalize vs Dispose
提问by tush1r
Why do some people use the Finalize
method over the Dispose
method?
为什么有些人用Finalize
方法而不用Dispose
方法?
In what situations would you use the Finalize
method over the Dispose
method and vice versa?
在什么情况下你会使用Finalize
方法而不是Dispose
方法,反之亦然?
采纳答案by Brian Rasmussen
Others have already covered the difference between Dispose
and Finalize
(btw the Finalize
method is still called a destructor in the language specification), so I'll just add a little about the scenarios where the Finalize
method comes in handy.
其他人已经介绍了Dispose
和之间的区别Finalize
(顺便说一句,该Finalize
方法在语言规范中仍称为析构函数),因此我将仅添加一些有关该Finalize
方法派上用场的场景。
Some types encapsulate disposable resources in a manner where it is easy to use and dispose of them in a single action. The general usage is often like this: open, read or write, close (Dispose). It fits very well with the using
construct.
某些类型以易于使用和在单个操作中处理它们的方式封装一次性资源。一般的用法往往是这样的:打开、读或写、关闭(Dispose)。它非常适合using
构造。
Others are a bit more difficult. WaitEventHandles
for instances are not used like this as they are used to signal from one thread to another. The question then becomes who should call Dispose
on these? As a safeguard types like these implement a Finalize
method, which makes sure resources are disposed when the instance is no longer referenced by the application.
其他的有点困难。WaitEventHandles
因为实例不是这样使用的,因为它们用于从一个线程向另一个线程发送信号。那么问题就变成了谁应该调用Dispose
这些?作为像这样的保护类型实现了一个Finalize
方法,该方法确保在应用程序不再引用实例时释放资源。
回答by Bhushan Bhangale
Finalize gets called by the GC when this object is no longer in use.
当该对象不再使用时,GC 会调用 Finalize。
Dispose is just a normal method which the user of this class can call to release any resources.
Dispose 只是一个普通的方法,这个类的用户可以调用它来释放任何资源。
If user forgot to call Dispose and if the class have Finalize implemented then GC will make sure it gets called.
如果用户忘记调用 Dispose 并且类已经实现了 Finalize,那么 GC 将确保它被调用。
回答by Samuel
The finalizer method is called when your object is garbage collected and you have no guarantee when this will happen (you can force it, but it will hurt performance).
当您的对象被垃圾回收时会调用终结器方法,并且您无法保证何时会发生这种情况(您可以强制使用它,但它会损害性能)。
The Dispose
method on the other hand is meant to be called by the code that created your class so that you can clean up and release any resources you have acquired (unmanaged data, database connections, file handles, etc) the moment the code is done with your object.
Dispose
另一方面,该方法旨在由创建您的类的代码调用,以便您可以在代码完成时清理和释放您获得的任何资源(非托管数据、数据库连接、文件句柄等)你的对象。
The standard practice is to implement IDisposable
and Dispose
so that you can use your object in a using
statment. Such as using(var foo = new MyObject()) { }
. And in your finalizer, you call Dispose
, just in case the calling code forgot to dispose of you.
标准做法是实现IDisposable
,Dispose
以便您可以在using
语句中使用您的对象。比如using(var foo = new MyObject()) { }
。在你的终结器中,你调用Dispose
,以防调用代码忘记处理你。
回答by itowlson
Finalize is the backstop method, called by the garbage collector when it reclaims an object. Dispose is the "deterministic cleanup" method, called by applications to release valuable native resources (window handles, database connections, etc.) when they are no longer needed, rather than leaving them held indefinitely until the GC gets round to the object.
Finalize 是 backstop 方法,由垃圾收集器在回收对象时调用。Dispose 是“确定性清理”方法,由应用程序调用以在不再需要有价值的本机资源(窗口句柄、数据库连接等)时释放它们,而不是无限期地保留它们,直到 GC 处理对象。
As the user of an object, you always use Dispose. Finalize is for the GC.
作为对象的用户,您总是使用 Dispose。Finalize 是针对 GC 的。
As the implementer of a class, if you hold managed resources that ought to be disposed, you implement Dispose. If you hold native resources, you implement both Dispose and Finalize, and both call a common method that releases the native resources. These idioms are typically combined through a private Dispose(bool disposing) method, which Dispose calls with true, and Finalize calls with false. This method always frees native resources, then checks the disposing parameter, and if it is true it disposes managed resources and calls GC.SuppressFinalize.
作为一个类的实现者,如果你持有应该被释放的托管资源,你就实现了 Dispose。如果你持有原生资源,你实现了 Dispose 和 Finalize,并且都调用了一个公共的方法来释放原生资源。这些习惯用法通常通过私有的 Dispose(bool disposing) 方法组合在一起,该方法使用 true 调用 Dispose,使用 false 调用 Finalize。此方法总是释放本机资源,然后检查处置参数,如果为真,则处置托管资源并调用 GC.SuppressFinalize。
回答by JP Alioto
99% of the time, you should not have to worry about either. :) But, if your objects hold references to non-managed resources (window handles, file handles, for example), you need to provide a way for your managed object to release those resources. Finalize gives implicit control over releasing resources. It is called by the garbage collector. Dispose is a way to give explicit control over a release of resources and can be called directly.
99% 的情况下,您都不应该担心。:) 但是,如果您的对象持有对非托管资源(例如窗口句柄、文件句柄)的引用,您需要为您的托管对象提供一种释放这些资源的方法。Finalize 提供了对释放资源的隐式控制。它由垃圾收集器调用。Dispose 是一种显式控制资源释放的方法,可以直接调用。
There is much much more to learn about the subject of Garbage Collection, but that's a start.
关于Garbage Collection的主题还有很多需要了解,但这只是一个开始。
回答by GenZiy
Finalize
敲定
- Finalizers should always be
protected
, notpublic
orprivate
so that the method cannot be called from the application's code directly and at the same time, it can make a call to thebase.Finalize
method - Finalizers should release unmanaged resources only.
- The framework does not guarantee that a finalizer will execute at all on any given instance.
- Never allocate memory in finalizers or call virtual methods from finalizers.
- Avoid synchronization and raising unhandled exceptions in the finalizers.
- The execution order of finalizers is non-deterministic—in other words, you can't rely on another object still being available within your finalizer.
- Do not define finalizers on value types.
- Don't create empty destructors. In other words, you should never explicitly define a destructor unless your class needs to clean up unmanaged resources and if you do define one, it should do some work. If, later, you no longer need to clean up unmanaged resources in the destructor, remove it altogether.
- Finalizers 应该始终是
protected
, notpublic
或者private
这样就不能直接从应用程序的代码中调用该base.Finalize
方法,同时它可以调用该方法 - 终结器应该只释放非托管资源。
- 该框架不保证终结器将在任何给定实例上执行。
- 永远不要在终结器中分配内存或从终结器调用虚拟方法。
- 避免在终结器中同步和引发未处理的异常。
- 终结器的执行顺序是不确定的——换句话说,你不能依赖另一个对象在你的终结器中仍然可用。
- 不要在值类型上定义终结器。
- 不要创建空的析构函数。换句话说,除非你的类需要清理非托管资源,否则你永远不应该显式定义析构函数,如果你定义了一个,它应该做一些工作。如果以后不再需要清理析构函数中的非托管资源,请将其完全删除。
Dispose
处置
- Implement
IDisposable
on every type that has a finalizer - Ensure that an object is made unusable after making a call to the
Dispose
method. In other words, avoid using an object after theDispose
method has been called on it. - Call
Dispose
on allIDisposable
types once you are done with them - Allow
Dispose
to be called multiple times without raising errors. - Suppress later calls to the finalizer from within the
Dispose
method using theGC.SuppressFinalize
method - Avoid creating disposable value types
- Avoid throwing exceptions from within
Dispose
methods
- 实现
IDisposable
对每一个都有一个终结类型 - 确保在调用
Dispose
方法后对象不可用。换句话说,避免在Dispose
方法被调用后使用对象。 - 完成
Dispose
所有IDisposable
类型后调用它们 - 允许
Dispose
多次调用而不会引发错误。 Dispose
使用该GC.SuppressFinalize
方法禁止以后从该方法中调用终结器- 避免创建一次性值类型
- 避免从
Dispose
方法内部抛出异常
Dispose/Finalized Pattern
处置/最终模式
- Microsoft recommends that you implement both
Dispose
andFinalize
when working with unmanaged resources. TheFinalize
implementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call theDispose
method explicitly. - Cleanup the unmanaged resources in the
Finalize
method as well asDispose
method. Additionally call theDispose
method for any .NET objects that you have as components inside that class(having unmanaged resources as their member) from theDispose
method.
- Microsoft 建议您在使用非托管资源时同时实现
Dispose
和Finalize
。该Finalize
实施将运行,当对象被垃圾收集,即使开发者忽略调用的资源仍然会发布Dispose
明确的方法。 - 清理
Finalize
方法和Dispose
方法中的非托管资源。此外,从该Dispose
方法中调用作为该类中的组件(具有非托管资源作为其成员)的任何 .NET 对象的Dispose
方法。
回答by Justin
The finalizer is for implicit cleanup - you should use this whenever a class manages resources that absolutely mustbe cleaned up as otherwise you would leak handles / memory etc...
终结器用于隐式清理 - 当一个类管理绝对必须清理的资源时,你应该使用它,否则你会泄漏句柄/内存等......
Correctly implementing a finalizer is notoriously difficult and should be avoided wherever possible - the SafeHandle
class (avaialble in .Net v2.0 and above) now means that you very rarely (if ever) need to implement a finalizer any more.
众所周知,正确实现终结器非常困难,应该尽可能避免 -SafeHandle
类(在 .Net v2.0 及更高版本中可用)现在意味着您很少(如果有的话)需要再实现终结器。
The IDisposable
interface is for explicit cleanup and is much more commonly used - you should use this to allow users to explicitly release or cleanup resources whenever they have finished using an object.
该IDisposable
接口用于显式清理并且更常用 - 您应该使用它来允许用户在他们完成使用对象时显式释放或清理资源。
Note that if you have a finalizer then you should also implement the IDisposable
interface to allow users to explicitly release those resources sooner than they would be if the object was garbage collected.
请注意,如果您有一个终结器,那么您还应该实现该IDisposable
接口,以允许用户比对象被垃圾收集时更快地显式释放这些资源。
See DG Update: Dispose, Finalization, and Resource Managementfor what I consider to be the best and most complete set of recommendations on finalizers and IDisposable
.
请参阅DG Update:Dispose、Finalization 和 Resource Management,了解我认为关于终结器和IDisposable
.
回答by MirlvsMaximvs
There're some keys about from the book MCSD Certification Toolkit (exam 70-483) pag 193:
MCSD 认证工具包(考试 70-483)第 193 页一书中有一些关键信息:
destructor ≈(it's almost equal to) base.Finalize(), The destructor is converted into an override version of the Finalize method that executes the destructor's code and then calls the base class's Finalize method. Then its totally non deterministic you can't able to know when will be called because depends on GC.
析构函数≈(它几乎等于) base.Finalize(),析构函数转换为Finalize方法的覆盖版本,执行析构函数的代码,然后调用基类的Finalize方法。然后它完全不确定,您无法知道何时会被调用,因为取决于 GC。
If a class contains no managed resources and no unmanaged resources, it doesn't need to implement IDisposableor have a destructor.
如果一个类不包含托管资源和非托管资源,则不需要实现 IDisposable 或具有析构函数。
If the class has only managed resources, it should implement IDisposable but it doesn't need a destructor. (When the destructor executes, you can't be sure managed objects still exist, so you can't call their Dispose methods anyway.)
如果类只有托管资源,它应该实现 IDisposable 但它不需要析构函数。(当析构函数执行时,您不能确定托管对象仍然存在,因此无论如何您都不能调用它们的 Dispose 方法。)
If the class has only unmanaged resources, it needs to implement IDisposable and needs a destructor in case the program doesn't call Dispose.
如果该类只有非托管资源,则它需要实现 IDisposable 并需要一个析构函数,以防程序不调用 Dispose。
The Dispose method must be safe to run more than once. You can achieve that by using a variable to keep track of whether it has been run before.
Dispose 方法必须可以安全运行多次。您可以通过使用变量来跟踪它之前是否已运行来实现这一点。
The Dispose method should free both managed and unmanaged resources.
Dispose 方法应该释放托管和非托管资源。
The destructor should free only unmanaged resources. (When the destructor executes, you can't be sure managed objects still exist, so you can't call their Dispose methods anyway.)
析构函数应该只释放非托管资源。(当析构函数执行时,您不能确定托管对象仍然存在,因此无论如何您都不能调用它们的 Dispose 方法。)
After freeing resources, the destructor should call GC.SuppressFinalize, so the object can skip the finalization queue.
释放资源后,析构函数应调用 GC.SuppressFinalize,以便对象可以跳过终结队列。
An Example of a an implementation for a class with unmanaged and managed resources:
具有非托管和托管资源的类的实现示例:
using System;
class DisposableClass : IDisposable
{
// A name to keep track of the object.
public string Name = "";
// Free managed and unmanaged resources.
public void Dispose()
{
FreeResources(true);
}
// Destructor to clean up unmanaged resources
// but not managed resources.
~DisposableClass()
{
FreeResources(false);
}
// Keep track if whether resources are already freed.
private bool ResourcesAreFreed = false;
// Free resources.
private void FreeResources(bool freeManagedResources)
{
Console.WriteLine(Name + ": FreeResources");
if (!ResourcesAreFreed)
{
// Dispose of managed resources if appropriate.
if (freeManagedResources)
{
// Dispose of managed resources here.
Console.WriteLine(Name + ": Dispose of managed resources");
}
// Dispose of unmanaged resources here.
Console.WriteLine(Name + ": Dispose of unmanaged resources");
// Remember that we have disposed of resources.
ResourcesAreFreed = true;
// We don't need the destructor because
// our resources are already freed.
GC.SuppressFinalize(this);
}
}
}
回答by isxaker
The best example which i know.
我所知道的最好的例子。
public abstract class DisposableType: IDisposable
{
bool disposed = false;
~DisposableType()
{
if (!disposed)
{
disposed = true;
Dispose(false);
}
}
public void Dispose()
{
if (!disposed)
{
disposed = true;
Dispose(true);
GC.SuppressFinalize(this);
}
}
public void Close()
{
Dispose();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// managed objects
}
// unmanaged objects and resources
}
}
回答by surin panda
As we know dispose and finalize both are used to free unmanaged resources.. but the difference is finalize uses two cycle to free the resources , where as dispose uses one cycle..
我们知道 dispose 和 finalize 都用于释放非托管资源.. 但区别在于 finalize 使用两个周期来释放资源,而 dispose 使用一个周期..