析构函数和Finalize()之间的那点事

如果我们在类中没有定义析构函数,则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.        

提示不要重写objectFinalize方法,而是提供析构函数的方式。即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中写了一个vitualFinalize()方法,这次是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方法(vitualvitual没关系),析构函数会自己再隐式的转换一个,一个类就有两个方法签名是一样的了,于是直接报错了,报的错也是说已经有一个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()'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值