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方法被调用的最常见的一种方式,因为虽 ...
随机推荐
- Function.identity()
Java 8允许在接口中加入具体方法.接口中的具体方法有两种,default方法和static方法,identity()就是Function接口的一个静态方法.Function.identity()返 ...
- [刘阳Java]_eayui-pagination分页组件_第5讲
分页组件也是很基本的应用,这里我只给出一段简单的代码 关键注意一点:分页组件可以在上面添加buttons按钮,或者自定义分页组件的外观.这些内容需要自行的查看EasyUI的API文档 <!DOC ...
- MySQL用B+树(而不是B树)做索引的原因
众所周知,MySQL的索引使用了B+树的数据结构.那么为什么不用B树呢? 先看一下B树和B+树的区别. B树 维基百科对B树的定义为"在计算机科学中,B树(B-tree)是一种树状数据结构, ...
- lucene 类介绍
lucene中重要的类: IndexWriter:lucene中最重要的类之一,主要用于索引的创建 Analyzer(抽象类):分析器,主要用于分析文本,常用的有StandardAnalyzer分析器 ...
- jenkins资源下载地址(软件、插件等)
jenkins资源下载地址(软件.插件等) 1. 镜像1:清华镜像 2 .镜像2:http://mirrors.jenkins-ci.org/ 3. 官方下载地址:https://jenkins.io ...
- K8S系列第三篇(Docker网络)
目录 docker 网络 Docker 的四种网络模 一.网络基础 1.网络名称空间介绍 2.创建一个命名空间 1)Veth设备对 2)Veth设备操作 1> 创建Veth设备对 2> 绑 ...
- odoo controllers 中type="Json" 或type="http"
服务端接收参考: # 导包 from odoo import http class HttpRequest(http.Controller): @http.route('/url', type='js ...
- Python自动化测试面试题-编程篇
目录 Python自动化测试面试题-经验篇 Python自动化测试面试题-用例设计篇 Python自动化测试面试题-Linux篇 Python自动化测试面试题-MySQL篇 Python自动化测试面试 ...
- 【用例】编写App测试用例的关注点
编写App测试用例的关注点 如何做到测试用例的百分百覆盖一直是测试用例编写过程中的难点,首先在测试时我们经常会遇见一些常见的bug,那么我们可以在编写测试用例时考虑到这些点. 一:关于业务逻辑 ...
- jvm源码解读--13 gc_root中的栈中oop的mark 和copy 过程分析
粘贴源码 package com.test; import java.util.Random; public class Test { static int number=12; private in ...


