Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.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# Dispose、Finalize、SuppressFinalize方法_C#_Garbage Collection - Fatal编程技术网

C# Dispose、Finalize、SuppressFinalize方法

C# Dispose、Finalize、SuppressFinalize方法,c#,garbage-collection,C#,Garbage Collection,我可以在同一个类中实现这两个方法吗 public class MyClass : IDisposable { // some implementation // if i missed to call Dispose() method; ~MyClass() { // it means, clear all does not mananage resources // but dont use Dispose() method } public void Di

我可以在同一个类中实现这两个方法吗

public class MyClass : IDisposable
{
  // some implementation
  // if i missed to call Dispose() method;
  ~MyClass()
  {
  // it means, clear all does not mananage resources 
  // but dont use Dispose() method 
  }
  public void Dispose()
  {
   // clear resources
   // if i call this method will i can do this:
   GC.SuppressFinalize()
   // it means dont use Finalizw method for this object
  }
}

我说得对吗?因为我不能理解这个GC.SuppressFinalize()方法?

是的,您可以实现您看到的两个方法

通常,如果对象可以同时具有托管引用和非托管引用,则正确的模式为:

public class MyClass : IDisposable
{
  ~MyClass()
  {
    Dispose(false);
  }
  public void Dispose()
  {
    GC.SuppressFinalize(this); 
    Dispose(true);
  }
  public virtual void Dispose(bool disposing)
  {
    if(disposing)
    {
      // clear MANAGED references
    }
    // free UNMANAGED resources
  }
}
但是您可以根据需要实现它。这只是一种模式。例如,如果您没有任何非托管资源,并且您的类是密封的(因此您可以确保它永远不会使用任何非托管资源),那么您可以像这样实现它:

public sealed class MyClass : IDisposable
{
  public void Dispose()
  {
    // release managed references
  }
}
忘了终结器吧

在第一种模式中,
GC.SuppresFinalize(this)
所做的是告诉垃圾收集器在释放对象时不应该调用终结器(
~MyClass()
方法):如果您专门调用了
Dispose()
,那么您已经调用了虚拟
Dispose(bool)
函数,为什么要再次调用它

问题是C#中的终结器本身是不确定的:您不知道何时调用它。。。您甚至不能保证它会被调用(尽管在正常清理过程中,如果以前没有调用它,它会被调用),这就是为什么
IDisposable
存在的原因,它是一种确定地释放阻塞对象的托管引用的方法,释放并释放由它分配的非托管资源

如果GC正在释放一个对象,那么它持有的所有托管引用也将被释放,因此在调用终结器时不需要清除托管引用

但是,您的应用程序应该尽最大努力释放和释放其拥有的任何非托管资源

如果忘记了
Dispose()
,则应该有最后一次机会释放它们(当GC收集对象时,或者在应用程序运行时进行最终清理时)。这就是为什么在正常模式下,您还实现了一个终结器,并告诉它清理非托管资源(如果您以前没有这样做)


请注意,与流行的观点相反,对
Dispose()
的调用没有什么特别之处,它只是一个方法调用:如果需要,可以调用
freeMObject()
FooBar()
。它不会使垃圾收集器释放任何内存。有一种模式使用了
IDisposable
,它非常重要,因此它有自己的语言语法结构(使用
块的
),但它只是一种模式。您可以执行与
Dispose()
相同的操作,而根本不实现
IDisposable

为什么方法public virtual void Dispose(bool disposing)被标记为virtual?这是否意味着在子类中,我们可以重写它,忘记释放基类的一些内存,并创建内存泄漏?@MishaHuziuk的想法是,派生类应该重写该方法,清理它们自己的资源(它们添加到派生类上的资源),然后调用
base.Dispose()
。当然,没有人阻止您不调用基方法并创建泄漏,但同样,没有人阻止您调用
GC.SuppressFinalize(this)
、或
Thread.Abort()
或类上可能会产生问题的任何其他内容。明白了。谢谢你!