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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 23:02:53  来源:igfitidea点击:

Finalize vs Dispose

c#dispose

提问by tush1r

Why do some people use the Finalizemethod over the Disposemethod?

为什么有些人用Finalize方法而不用Dispose方法?

In what situations would you use the Finalizemethod over the Disposemethod and vice versa?

在什么情况下你会使用Finalize方法而不是Dispose方法,反之亦然?

采纳答案by Brian Rasmussen

Others have already covered the difference between Disposeand Finalize(btw the Finalizemethod is still called a destructor in the language specification), so I'll just add a little about the scenarios where the Finalizemethod 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 usingconstruct.

某些类型以易于使用和在单个操作中处理它们的方式封装一次性资源。一般的用法往往是这样的:打开、读或写、关闭(Dispose)。它非常适合using构造。

Others are a bit more difficult. WaitEventHandlesfor instances are not used like this as they are used to signal from one thread to another. The question then becomes who should call Disposeon these? As a safeguard types like these implement a Finalizemethod, 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 Disposemethod 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 IDisposableand Disposeso that you can use your object in a usingstatment. 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.

标准做法是实现IDisposableDispose以便您可以在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, not publicor privateso that the method cannot be called from the application's code directly and at the same time, it can make a call to the base.Finalizemethod
  • 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 IDisposableon every type that has a finalizer
  • Ensure that an object is made unusable after making a call to the Disposemethod. In other words, avoid using an object after the Disposemethod has been called on it.
  • Call Disposeon all IDisposabletypes once you are done with them
  • Allow Disposeto be called multiple times without raising errors.
  • Suppress later calls to the finalizer from within the Disposemethod using the GC.SuppressFinalizemethod
  • Avoid creating disposable value types
  • Avoid throwing exceptions from within Disposemethods
  • 实现IDisposable对每一个都有一个终结类型
  • 确保在调用Dispose方法后对象不可用。换句话说,避免在Dispose方法被调用后使用对象。
  • 完成Dispose所有IDisposable类型后调用它们
  • 允许Dispose多次调用而不会引发错误。
  • Dispose使用该GC.SuppressFinalize方法禁止以后从该方法中调用终结器
  • 避免创建一次性值类型
  • 避免从Dispose方法内部抛出异常

Dispose/Finalized Pattern

处置/最终模式

  • Microsoft recommends that you implement both Disposeand Finalizewhen working with unmanaged resources. The Finalizeimplementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call the Disposemethod explicitly.
  • Cleanup the unmanaged resources in the Finalizemethod as well as Disposemethod. Additionally call the Disposemethod for any .NET objects that you have as components inside that class(having unmanaged resources as their member) from the Disposemethod.
  • Microsoft 建议您在使用非托管资源时同时实现DisposeFinalize。该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 SafeHandleclass (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 IDisposableinterface 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 IDisposableinterface 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 使用一个周期..