ninputer在关于“值类型的Finalize不会被调用”中(http://blog.joycode.com/lijianzhong/archive/2005/01/13/42991.aspx#FeedBack)评论到“VB对Finalize管的可松呢,可以直接重写、直接调用、允许不调用父类的Finalize,或者多次调用父类的Finalize等等…… 完全不像C#”。

其实C#的Finalize方法看起来只是比VB的好一点,但仍然有非常隐蔽的问题。问题如下。

首先来看如下的代码:

using System; 

public class Grandpapa 

     ~Grandpapa(){ Console.WriteLine("Grandpapa.~Grandpapa");} 


public class Parent:Grandpapa 

     ~Parent(){ Console.WriteLine("Parent.~Parent");} 


public class Son:Parent 

     ~Son(){ Console.WriteLine("Son.~Son");} 


public class App 

     public static void Main() 
     { 
         Son s=new Son(); 
  
         GC.Collect(); 
         GC.WaitForPendingFinalizers(); 
     } 
}

这段代码的运行结果毫无疑问是:

Son.~Son 
Parent.~Parent 
Grandpapa.~Grandpapa

这没什么问题。但是如果将Parent类重新定义如下,会出现什么情况呢?

public class Parent:Grandpapa 

     protected void Finalize(){ Console.WriteLine("Parent.Finalize");} 
}

运行结果变成了:

Son.~Son 
Parent.Finalize

情况已经有些不妙了,我在Parent中定义了一个“普通”的Finalize方法,竟然被它的子类Son的析构器给调用了?

当然Finalize方法在C#中并不是一个“普通”的方法,析构器编译后就是一个有上述签名的Finalize方法。但C#编译器并没有禁止我们定义“普通”的Finalize,

C#规范也没有指出定义这样的Finalize方法就是在定义一个析构器——实际上也不是,只是上述代码的表现如此——甚至还有这样一句诱人犯错的话:The compiler behaves as if this method(Finalize), and overrides of it, do not exist at all。分析IL代码可以看出,Parent中定义的“普通”的Finalize方法实际上“欺骗”了它的子类。它的子类只关心其父类是否定义了Finalize(当然签名要为上述形式)方法,它并不关心那个Finalize方法是否具有“析构器”语义。

如果上述代码的行为通过理性分析还算可以接受的话,那么下面代码的运行结果就令人眩晕了,将Parent类重新定义如下(在上面的基础上添加了一个virtual关键字):

public class Parent:Grandpapa 

     protected virtual void Finalize(){ Console.WriteLine("Parent.Finalize");} 
}

编译后运行结果如下:

Grandpapa.~Grandpapa

C#中Finalize方法的问题的更多相关文章

  1. Java中finalize方法用途何在?

    package thinking.in.java.demo; /* * finalize的用途何在? * *本例的终止条件是L所有的Book对象在被当做垃圾回收前都应该被签入.但是在main方法中 * ...

  2. Java中finalize()方法的作用

    finalize方法是Object提供的的实例方法,使用规则如下: 当对象不再被任何对象引用时,GC会调用该对象的finalize()方法 finalize()是Object的方法,子类可以覆盖这个方 ...

  3. 为什么在Java中不使用finalize()方法

    我们都知道finalize()方法是回收分配给对象的内存之前调用垃圾收集器线程的基本语句.在这篇文章中,我们将会深入这个方法. 这篇文章中的章节: 1.finalize()方法不能保证执行(这个将要用 ...

  4. JAVA中的finalize()方法

    [转]JAVA中的finalize()方法 今天早上看Thinking in java的[第四章 初始化和清除].[  清除:终结和垃圾回收]的时候, 看到了这个东西. 用于清理滴... 当然,这个方 ...

  5. JAVA中GC时finalize()方法是不是一定会被执行?

    在回答上面问题之前,我们一定要了解JVM在进行垃圾回收时的机制,首先: 一.可达性算法  要知道对象什么时候死亡,我们需要先知道JVM的GC是如何判断对象是可以回收的.JAVA是通过可达性算法来来判断 ...

  6. finalize() 方法——Java中垃圾回收提醒方法

    finalize() Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象. 例如,你可以使用 finalize() 来确保 ...

  7. Java对象中的finalize()方法使用说明

    我在写java程序的时候,从来没有遇见过是用Object.finalize()的时候,但是在学习Java虚拟机的垃圾回收机制时,虚拟机在进行垃圾回收时需要使用finalize()方法来进行对象清理.下 ...

  8. 禁止使用finalize方法

    Don´t use Finalizers, mainly because are unpredictable and we don´t know when will be executed, &quo ...

  9. 第五节:什么导致Finalize方法被调用

    Finalize方法在垃圾回收结束时被调用,下面有5种事件会导致开始垃圾回收 1.第0代已满    第0代已满,垃圾回收会自动开始.该事件是目前导致Finalize方法被调用的最常见的一种方式,因为虽 ...

随机推荐

  1. vmare下克隆一台linux

    第一步:点击"克隆"按钮,注意,克隆之前选择的机器需要关机 第二步:接下来需要改一下新机器的mac地址,选中新机器,右键"设置"-->"网络适配 ...

  2. DWA局部路径规划算法论文阅读:The Dynamic Window Approach to Collision Avoidance。

    DWA(动态窗口)算法是用于局部路径规划的算法,已经在ROS中实现,在move_base堆栈中:http://wiki.ros.org/dwa_local_planner DWA算法第一次提出应该是1 ...

  3. PLICP

    介绍 PLICP相比较于普通ICP算法,使用点线之间的距离作为度量,最终找到一个最小化该度量的闭式解(解析解). 最优结果以平方的速度收敛.相比较于ICP,IDC,MBICP.PLICP更加准确,且需 ...

  4. POJ 尺取法

    poj3061 Subsequence 题目链接: http://poj.org/problem?id=3061 挑战P146.题意:给定长度为n的数列整数a0,a1,...,a(n-1)以及整数S, ...

  5. 【系统配置】Ubuntu和Windons系统安装配置深度学习环境

    Ubuntu系统 1.备份 在服务器上整个装系统之前,需要做好一个工作,也就是相关重要数据的备份,这里主要是将固态中的数据备份到机械硬盘或移动硬盘里,可能在备份的过程中会遇到无法写入的问题,是因为文件 ...

  6. 每天五分钟Go - 变量

    变量的声明 1.使用关键词 var 定义,声明后若不赋值,则使用默认值 var 变量名 [变量类型] [=初始值] var a,b,c string var e,f int = 0,1 声明时,如果省 ...

  7. java 向Redis中存放数据 List<Device>转String

    /** * redis服务 */ @Autowired private RedisService redisService; //创建 Device  对象 Device no = new Devic ...

  8. python 之爬虫基本流程

    python 之爬虫基本流程 一 用户获取网络数据的方式: 方式1:浏览器提交请求--->下载网页代码--->解析成页面 方式2:模拟浏览器发送请求(获取网页代码)->提取有用的数据 ...

  9. "virtualbox for mac安装器遇到了一个错误, 导致安装失败. 请联系软件制造商以获得帮助"的解决办法

    virtualbox下载地址: https://www.virtualbox.org/wiki/Downloads 原因:"Mac OS 10.13.4 会阻止外部内核扩展的安装" ...

  10. promise详解 : 实现promise(附实现代码)

    promise then 的特点 : then 函数的返回值是一个 promise, 可以继续调用 then 函数 回调函数 resolve 和 reject 的参数 value /reason, 可 ...