如果我们在类中没有定义析构函数,则CLR不会自动给这个类添加一个析构函数。代码如下:
using System;
using System.Collections.Generic;
using System.Text;
namespace OwnFinalize
{
class TestOwnFinalize
{
static void Main(string[] args)
{
Console.ReadLine();
}
}
}
转换成IL语言如下:
.class private auto ansi beforefieldinit TestOwnFinalize
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: ret
}
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 8
L_0000: nop
L_0001: call string [mscorlib]System.Console::ReadLine()
L_0006: pop
L_0007: ret
}
}
从上面的IL语言中只看到了CLR自动生成的构造函数,没有看到自动生成析构函数,即没看到自动生成Finalize()方法。
接着往下看:
我们自己在类中定义一个Finalize(),签名如下:
protected virtual void Finalize(){}
编译的时候,编译器会提一个警告:自己写的Finalize()方法会干扰析构函数的工作,但并没有报错。
在自己写的这个Finalize()方法中,我并没有try{}finally{},没有调用父类的Finalize(),这样的话,实际上会把析构的链给打断了。而且这个方法不管是不是vitual的,都会有这种效果。
接着往下看:
如果我们定义这个Finalize(),并且是override基类即Object类的该方法时,编译器就按捺不住了,提示一条错误信息:
Do not override object.Finalize. Instead, provide a destructor.
提示不要重写object的Finalize方法,而是提供析构函数的方式。即Object类的Finalize方法是不能被override的。
接着往下看:
我们把代码写成下面这样,又会怎么样呢?
using System;
using System.Collections.Generic;
using System.Text;
namespace OwnFinalize
{
class TestOwnFinalize
{
static void Main(string[] args)
{
TestOwnFinalize o = new TestOwnFinalize();
o.Finalize();
Console.ReadLine();
}
protected virtual void Finalize()
{
Console.WriteLine("我不是由析构函数隐式转换的,我是手写的!");
}
}
class TestOverrideFinalize: TestOwnFinalize
{
protected override void Finalize()
{
base.Finalize();
}
}
}
我们在父类TestOwnFinalize中写了一个vitual的Finalize()方法,这次是vitual的,而不是override基类即Object类的Finalize()方法,在子类TestOverrideFinalize中override父类TestOwnFinalize的Finalize()方法,这次编译器没有发火,只是警告了一下,还是警告自己写Finalize方法会干扰析构函数的执行,不管了,谁让你不是错误而只是个警告。
接着往下看:
如果我们在一个类中即定义了析构函数,又手写了Finalize方法,那结果又会怎么样呢?
using System;
using System.Collections.Generic;
using System.Text;
namespace OwnFinalize
{
class TestOwnFinalize
{
static void Main(string[] args)
{
TestOwnFinalize o = new TestOwnFinalize();
o.Finalize();
Console.ReadLine();
}
~TestOwnFinalize()
{
Console.WriteLine("I am descontructor");
}
protected virtual void Finalize()
{
Console.WriteLine("I am HandWrite");
}
}
}
这次,编译器还是很严格,发现已经有了一个Finalize方法(vitual不vitual没关系),析构函数会自己再隐式的转换一个,一个类就有两个方法签名是一样的了,于是直接报错了,报的错也是说已经有一个Finalize方法、分不清了,如下:
1)Type 'OwnFinalize.TestOwnFinalize' already defines a member called 'Finalize' with the same
2)The call is ambiguous between the following methods or properties: 'OwnFinalize.TestOwnFinalize.~TestOwnFinalize()' and 'OwnFinalize.TestOwnFinalize.Finalize()'