Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 最终确定与处置_C#_Dispose - Fatal编程技术网

C# 最终确定与处置

C# 最终确定与处置,c#,dispose,C#,Dispose,为什么有些人使用Finalize方法而不是Dispose方法 在什么情况下,您会使用Finalize方法而不是Dispose方法,反之亦然?当此对象不再使用时,GC会调用Finalize Dispose只是一个普通的方法,该类的用户可以调用它来释放任何资源 如果用户忘记调用Dispose,并且类已实现Finalize,则GC将确保调用它。当对象被垃圾收集时,将调用finalizer方法,并且您无法保证何时会发生这种情况(您可以强制它,但会影响性能) 另一方面,Dispose方法是由创建类的代码调

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


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

当此对象不再使用时,GC会调用Finalize

Dispose只是一个普通的方法,该类的用户可以调用它来释放任何资源


如果用户忘记调用Dispose,并且类已实现Finalize,则GC将确保调用它。

当对象被垃圾收集时,将调用finalizer方法,并且您无法保证何时会发生这种情况(您可以强制它,但会影响性能)

另一方面,
Dispose
方法是由创建类的代码调用的,这样您就可以在对对象执行代码时清理并释放您获得的任何资源(非托管数据、数据库连接、文件句柄等)


标准做法是实现
IDisposable
Dispose
,以便您可以在
状态中使用对象。例如
使用(var foo=new MyObject()){}
。在终结器中,您调用
Dispose
,以防调用代码忘记处置您。

Finalize是backstop方法,垃圾收集器在回收对象时调用。Dispose是“确定性清理”方法,由应用程序调用,以在不再需要有价值的本机资源(窗口句柄、数据库连接等)时释放它们,而不是将它们无限期地保留,直到GC开始处理对象

作为对象的用户,始终使用Dispose。最后定稿是为总承包商准备的


作为类的实现者,如果您持有应该被处置的托管资源,那么您将实现Dispose。如果您持有本机资源,则可以实现Dispose和Finalize,并调用释放本机资源的公共方法。这些习惯用法通常通过私有Dispose(bool disposing)方法组合在一起,该方法使用true处理调用,使用false完成调用。此方法总是释放本机资源,然后检查disposing参数,如果该参数为true,则它将处理托管资源并调用GC.SuppressFinalize。

99%的时间,您不必担心这两种情况。:)但是,如果对象包含对非托管资源(例如窗口句柄、文件句柄)的引用,则需要为托管对象提供释放这些资源的方法。Finalize为释放资源提供隐式控制。它由垃圾收集器调用。Dispose是一种对资源释放进行显式控制的方法,可以直接调用


关于的主题还有很多要学习的,但这只是一个开始。

其他人已经讨论了
Dispose
Finalize
之间的区别(顺便说一句,
Finalize
方法在语言规范中仍然称为析构函数),因此,我只想添加一点关于
Finalize
方法派上用场的场景

有些类型以一种方式封装了一次性资源,在一次操作中就可以轻松地使用和处置这些资源。通常的用法是:打开、读或写、关闭(Dispose)。它非常适合使用
构造的


其他的则有点困难<代码>WaitEventHandles
对于实例来说并不是这样使用的,因为它们用于从一个线程向另一个线程发送信号。接下来的问题是,谁应该调用
Dispose
?作为一种保护措施,这些类型实现了一个
Finalize
方法,该方法确保在应用程序不再引用实例时释放资源

完成

  • 终结器应始终受到
    保护
    ,而不是
    公共
    私有
    ,以便无法直接从应用程序的代码调用该方法,同时,它可以调用
    基。终结
    方法
  • 终结器应仅释放非托管资源
  • 该框架不保证终结器将在任何给定实例上执行
  • 决不要在终结器中分配内存或从终结器中调用虚拟方法
  • 避免在终结器中同步和引发未处理的异常
  • 终结器的执行顺序是不确定的,换句话说,您不能依赖终结器中仍然可用的另一个对象
  • 不要在值类型上定义终结器
  • 不要创建空的析构函数。换句话说,除非您的类需要清理非托管资源,否则您永远不应该显式定义析构函数,如果您确实定义了一个析构函数,它应该做一些工作。如果以后不再需要清理析构函数中的非托管资源,请将其全部删除
处置

  • 在每个具有终结器的类型上实现
    IDisposable
  • 确保在调用
    Dispose
    方法后对象变得不可用。换句话说,避免在对对象调用
    Dispose
    方法后使用该对象
  • 处理完所有
    IDisposable
    类型后,对它们调用
    Dispose
  • 允许多次调用
    Dispose
    ,而不会引发错误
  • 使用
    GC.SuppressFinalize
    方法从
    Dispose
    方法中抑制以后对终结器的调用
  • 避免创建一次性值类型
  • 避免从
    Dispose
    方法中引发异常
处理/最终确定的模式

  • Microsoft建议您在使用非托管资源时同时实现
    Dispose
    Finalize
    完成
    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);
    
            // We don't need the destructor because
            // our resources are already freed.
            GC.SuppressFinalize(this);
        }
    
        // 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;
            }
        }
    }
    
     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
        }
      }
    
    class ClassWithDisposeAndFinalize : IDisposable
    {
        // Used to determine if Dispose() has already been called, so that the finalizer
        // knows if it needs to clean up unmanaged resources.
         private bool disposed = false;
    
         public void Dispose()
         {
           // Call our shared helper method.
           // Specifying "true" signifies that the object user triggered the cleanup.
              CleanUp(true);
    
           // Now suppress finalization to make sure that the Finalize method 
           // doesn't attempt to clean up unmanaged resources.
              GC.SuppressFinalize(this);
         }
         private void CleanUp(bool disposing)
         {
            // Be sure we have not already been disposed!
            if (!this.disposed)
            {
                 // If disposing equals true i.e. if disposed explicitly, dispose all 
                 // managed resources.
                if (disposing)
                {
                 // Dispose managed resources.
                }
                 // Clean up unmanaged resources here.
            }
            disposed = true;
          }
    
          // the below is called the destructor or Finalizer
         ~ClassWithDisposeAndFinalize()
         {
            // Call our shared helper method.
            // Specifying "false" signifies that the GC triggered the cleanup.
            CleanUp(false);
         }