为什么Finalize方法不适用于自定义类型

时间:2014-08-23 23:17:51

标签: c# garbage-collection

由于Finalize()在Object中定义受保护,所有内容都是从Object派生的。为什么Finalize()与Equal()和ToString()不同,(派生)自定义类型不能直接在C#中调用?我并不是说它应该被调用,而只是想知道为什么它不可用。

2 个答案:

答案 0 :(得分:2)

要简单地扩展@HansPassant的含义,让我们检查一个例子。

System.IO.FileStream定义了终结器,(我使用ILSpy来反编译代码),

// System.IO.FileStream
~FileStream()
{
    if (this._handle != null)
    {
        this.Dispose(false);
    }
}

好的,现在在ILSpy中,让我们将语言从C#切换到IL,

.method family hidebysig virtual 
    instance void Finalize () cil managed 
{
    // Method begins at RVA 0xb4154
    // Code size 25 (0x19)
    .maxstack 2

    .try
    {
        IL_0000: ldarg.0
        IL_0001: ldfld class Microsoft.Win32.SafeHandles.SafeFileHandle System.IO.FileStream::_handle
        IL_0006: brfalse.s IL_000f

        IL_0008: ldarg.0
        IL_0009: ldc.i4.0
        IL_000a: callvirt instance void System.IO.Stream::Dispose(bool)

        IL_000f: leave.s IL_0018
    } // end .try
    finally
    {
        IL_0011: ldarg.0
        IL_0012: call instance void System.Object::Finalize()
        IL_0017: endfinally
    } // end handler

    IL_0018: ret
} // end of method FileStream::Finalize
你现在明白了吗?在C#中定义终结器时,C#编译器会将其转换为覆盖System.Object.Finalize的函数。因此,仅对于这个Finalize方法,在C#中覆盖它的唯一方法是定义终结器。

答案 1 :(得分:-1)

MSDN文档在本主题中非常困惑。

  

您应该为使用非托管资源的类重写Finalize,例如文件句柄或数据库连接,当在垃圾回收期间丢弃使用它们的托管对象时,必须释放这些资源。

另一方面(这很重要):

  

C#编译器不允许您覆盖Finalize方法。相反,您通过为您的类实现析构函数来提供终结器。

我认为Finalize()是针对基本类型定义的,因为carbage收集。析构函数具有相同的目的。