C#中Finalize方法的问题
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方法的问题的更多相关文章
- Java中finalize方法用途何在?
package thinking.in.java.demo; /* * finalize的用途何在? * *本例的终止条件是L所有的Book对象在被当做垃圾回收前都应该被签入.但是在main方法中 * ...
- Java中finalize()方法的作用
finalize方法是Object提供的的实例方法,使用规则如下: 当对象不再被任何对象引用时,GC会调用该对象的finalize()方法 finalize()是Object的方法,子类可以覆盖这个方 ...
- 为什么在Java中不使用finalize()方法
我们都知道finalize()方法是回收分配给对象的内存之前调用垃圾收集器线程的基本语句.在这篇文章中,我们将会深入这个方法. 这篇文章中的章节: 1.finalize()方法不能保证执行(这个将要用 ...
- JAVA中的finalize()方法
[转]JAVA中的finalize()方法 今天早上看Thinking in java的[第四章 初始化和清除].[ 清除:终结和垃圾回收]的时候, 看到了这个东西. 用于清理滴... 当然,这个方 ...
- JAVA中GC时finalize()方法是不是一定会被执行?
在回答上面问题之前,我们一定要了解JVM在进行垃圾回收时的机制,首先: 一.可达性算法 要知道对象什么时候死亡,我们需要先知道JVM的GC是如何判断对象是可以回收的.JAVA是通过可达性算法来来判断 ...
- finalize() 方法——Java中垃圾回收提醒方法
finalize() Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象. 例如,你可以使用 finalize() 来确保 ...
- Java对象中的finalize()方法使用说明
我在写java程序的时候,从来没有遇见过是用Object.finalize()的时候,但是在学习Java虚拟机的垃圾回收机制时,虚拟机在进行垃圾回收时需要使用finalize()方法来进行对象清理.下 ...
- 禁止使用finalize方法
Don´t use Finalizers, mainly because are unpredictable and we don´t know when will be executed, &quo ...
- 第五节:什么导致Finalize方法被调用
Finalize方法在垃圾回收结束时被调用,下面有5种事件会导致开始垃圾回收 1.第0代已满 第0代已满,垃圾回收会自动开始.该事件是目前导致Finalize方法被调用的最常见的一种方式,因为虽 ...
随机推荐
- 北京大公司:你是熟悉Map集合吗?
<对线面试官>系列目前已经连载30篇啦,这是一个讲人话面试系列 [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 &am ...
- python 图像读取与显示
import aircv as ac import matplotlib.pyplot as plt '''imshow()函数格式为: matplotlib.pyplot.imshow(X, cma ...
- ES6新增语法(七)——async...await
什么是async async的意思是"异步",顾名思义就是有关异步操作的关键字,async 是 ES7 才有的,与我们之前说的Promise.Generator有很大的关联. 使用 ...
- [SHOI2014]概率充电器 题解
注意到本题的贡献是不带权的,所以期望其实就是每个点的概率之和. 本题正着做好像不是很好做,要考虑 \(P(A+B)=P(A)+P(B)-P(A)P(B)\) 的容斥(因为这是两个条件至少满足一个,所以 ...
- python---replace函数
描述 Python replace() 方法把字符串中的 old(旧字符串) 替换成 new(新字符串),如果指定第三个参数max,则替换不超过 max 次. 语法 replace()方法语法: st ...
- PL SQL Developer 13连接Oracle数据库并导出数据
下载 并安装 PL SQL Developer 13,默认支持中文语言 ============================= 注册码: product code: 4vkjwhfeh3ufnqn ...
- VUE SpringCloud 跨域资源共享 CORS 详解
VUE SpringCloud 跨域资源共享 CORS 详解 作者: 张艳涛 日期: 2020年7月28日 本篇文章主要参考:阮一峰的网络日志 » 首页 » 档案 --跨域资源共享 CORS 详解 ...
- window.location.href下载文件,文件名中文乱码处理
下载文件方法: window.location.href='http://www.baidu.com/down/downFile.txt?name=资源文件'; 这种情况下载时:文件名资源文件会中文乱 ...
- URI 未注册(设置 | 语言和框架 | 架构和 DTD)
创建xml文件导入资源出错 解决方法:点击左边的小红灯,选择获取外部资源,加载资源即可
- 【数据结构与算法】字符串匹配(Rabin-Karp 算法和KMP 算法)
Rabin-Karp 算法 概念 用于在 一个字符串 中查找 另外一个字符串 出现的位置. 与暴力法不同,基本原理就是比较字符串的 哈希码 ( HashCode ) , 快速的确定子字符串是否等于被查 ...