如何在C#中重写Finalize()方法?

8
以下函数会出现编译错误:“不要覆盖对象的Finalize方法,而是提供一个析构函数。”
protected override void Finalize()
{           
    this.Dispose();
    base.Finalize();
}
3个回答

21

最终器方法被称为 ~name(),其中将 "name" 替换为您的类名。

C# 编译器将从此生成 finalizer 方法。

但请注意:

  1. 仅在确实需要时才使用 finalizer:您的类型直接包含本机资源(使用包装程序的类型仅使用 Dispose 模式)。
  2. 考虑特化 SafeHandle 而不是编写自己的。
  3. 实现 Dispose 模式以允许调用方快速释放资源。
  4. 确保您的 Dispose 和 Finalizer 是幂等的,可以安全地多次调用。

例如:

class MyClass : IDisposable {
  private IntPtr SomeNativeResource;

  ~MyClass() {
    Dispose(false);
  }

  public void Dispose() {
    Dispose(true);
  }

  protected virtual void Dispose(bool disposing) {
    if (disposing) {
      // Dispose any disposable fields here
      GC.SuppressFinalize(this);
    }
    ReleaseNativeResource();
  }
}

子类可以重写Dispose(bool)方法来添加任何额外的字段并调用基本实现。

编辑:增加有关何时完成的示例和注释。


你想念了 void 吗? - Lei Yang
@LeiYang:是的,两次。而且,在将近6年后(!),现在已经修复了。 - Richard

9

不需要。

听从编译器。您不应该覆盖Finalize方法。相反,您应该实现IDisposable接口并重写Dispose方法。

除非您明确需要释放对象直接持有的资源,否则您应该能够在Dispose方法中完成所有需要的操作。

但是如果您必须这样做:

public class MyClass
{
    public MyClass() { ... } // Constructor
    public ~MyClass() { ... } // Destructor/Finalizer
}

要小心Finalizers,因为如果实现不当,可能会带来相当大的性能开销。


0

听取编译器错误的建议,它们比它们的年龄更加睿智(除非你真的需要,在极少数情况下,实际上要干扰终结器...在 C# 中命名有点反过来)。

相反,你应该实现 Dispose(),使你的类实现 IDisposable,像这样:

public class MyClass : IDisposable
{
  public void Dispose()
  {
    //cleanup
  }
}

然后在使用您的类时,将其包装在{{link1:using}}中,就像这样:

using(var mc = new MyClass()) {
 //use it for things
} //it gets disposed here

1
然后,在使用您的类时,像这样将其包装在 using 中:using(var mc = new MyClass()) { //用它来做一些事情 } //它会在这里被处理掉请详细说明,因为我还没有使用过 "using"。 - Ramakant Badolia
1
@Ramakant - using() 是用于立即释放对象的语句,例如文件句柄,使用方式如下:using (var r = File.OpenText("myFile.log")) { //do stuff with the reader.. },在该语句结束时,文件句柄会被立即关闭,释放锁和资源。 - Nick Craver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接