全面解读C#编程中的析构函数用法
作者:goldensun 发布时间:2021-05-24 00:27:33
析构函数用于析构类的实例。
备注
不能在结构中定义析构函数。只能对类使用析构函数。
一个类只能有一个析构函数。
无法继承或重载析构函数。
无法调用析构函数。它们是被自动调用的。
析构函数既没有修饰符,也没有参数。
例如,下面是类 Car 的析构函数的声明:
class Car
{
~Car() // destructor
{
// cleanup statements...
}
}
该析构函数隐式地对对象的基类调用 Finalize。这样,前面的析构函数代码被隐式地转换为以下代码:
protected override void Finalize()
{
try
{
// Cleanup statements...
}
finally
{
base.Finalize();
}
}
这意味着对继承链中的所有实例递归地调用 Finalize 方法(从派生程度最大的到派生程度最小的)。
注意
不应使用空析构函数。如果类包含析构函数,Finalize 队列中则会创建一个项。调用析构函数时,将调用垃圾回收器来处理该队列。如果析构函数为空,只会导致不必要的性能损失。
程序员无法控制何时调用析构函数,因为这是由垃圾回收器决定的。垃圾回收器检查是否存在应用程序不再使用的对象。如果垃圾回收器认为某个对象符合析构,则调用析构函数(如果有)并回收用来存储此对象的内存。程序退出时也会调用析构函数。
可以通过调用 Collect 强制进行垃圾回收,但大多数情况下应避免这样做,因为这样会导致性能问题。
使用析构函数释放资源
通常,与运行时不进行垃圾回收的开发语言相比,C# 无需太多的内存管理。这是因为 .NET Framework 垃圾回收器会隐式地管理对象的内存分配和释放。但是,当应用程序封装窗口、文件和网络连接这类非托管资源时,应当使用析构函数释放这些资源。当对象符合析构时,垃圾回收器将运行对象的 Finalize 方法。
资源的显式释放
如果您的应用程序在使用昂贵的外部资源,我们还建议您提供一种在垃圾回收器释放对象前显式地释放资源的方式。可通过实现来自 IDisposable 接口的 Dispose 方法来完成这一点,该方法为对象执行必要的清理。这样可大大提高应用程序的性能。即使有这种对资源的显式控制,析构函数也是一种保护措施,可用来在对 Dispose 方法的调用失败时清理资源。
下面的示例创建三个类,这三个类构成了一个继承链。类 First 是基类,Second 是从 First 派生的,而 Third 是从 Second 派生的。这三个类都有析构函数。在 Main() 中,创建了派生程度最大的类的实例。注意:程序运行时,这三个类的析构函数将自动被调用,并且是按照从派生程度最大的到派生程度最小的次序调用。
class First
{
~First()
{
System.Diagnostics.Trace.WriteLine("First's destructor is called.");
}
}
class Second : First
{
~Second()
{
System.Diagnostics.Trace.WriteLine("Second's destructor is called.");
}
}
class Third : Second
{
~Third()
{
System.Diagnostics.Trace.WriteLine("Third's destructor is called.");
}
}
class TestDestructors
{
static void Main()
{
Third t = new Third();
}
}
输出:
Third's destructor is called.
Second's destructor is called.
First's destructor is called.
析构函数与Dispose()方法的区别
1. Dispose需要实现IDisposable接口。
2. Dispose由开发人员代码调用,而析构函数由GC自动调用。
3. Dispose方法应释放所有托管和非托管资源。而析构函数只应释放非托管资源。因为析构函数由GC来判断调用,当GC判断某个对象不再需要的时候,则调用其析构方法,这时候该对象中可能还包含有其他有用的托管资源。
4. 通过系统GC频繁的调用析构方法来释放资源会降低系统性能,所以推荐显示调用Dispose方法。
5. Dispose方法结尾处加上代码“GC.SuppressFinalize(this);”,即告诉GC不需要再调用该对象的析构方法,否则,GC仍会在判断该对象不再有用后调用其析构方法,虽然程序不会出错,但影响系统性能。
6、析构函数 和 Dispose 释放的资源应该相同,这样即使类使用者在没有调用 Dispose 的情况下,资源也会在 Finalize 中得到释放。
7、Finalize 不应为 public。
8、有 Dispose 方法存在时,应该调用它,因为 Finalize 释放资源通常是很慢的。


猜你喜欢
- 前言学习自定义view,想找点东西耍一下,刚好看到抖音的点赞效果不错,尝试一下。抖音效果: 话不多说,先上代码:public class L
- 项目背景:在项目中包含两个定时任务,配置信息如下:1、@Scheduled(initialDelay = 1,fixedDelay=1000
- Spring实例Bean的方法Spring实例Bean的方法,在AbstractAutowireCapableBeanFactory中的pr
- //param objArr the expanded object of Array. &
- 本文章是基于鸿洋的Android 自定义View (一) 的一些扩展,以及对Android自定义View构造函数详解里面内容的一些转载。首先
- 本文实例讲述了C#关闭指定名字进程的方法。分享给大家供大家参考。具体实现方法如下:public static void stopNamedP
- 1. 概述将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。2. 解决的问题当希望忽
- 本文实例为大家分享了java实现邮箱群发的具体代码,供大家参考,具体内容如下近来无事,在网上看了一些大牛文章,其中看到一篇比较好的,分享给大
- 一、LINQ的体系结构语言集成查询 (LINQ) (C#) | Microsoft 官方文档LINQ总共包括五个部分: 程序集命名
- 还是我们自定View的那几个步骤:1、自定义View的属性2、在View的构造方法中获得我们自定义的属性[ 3、重写onMesure ]4、
- using System;using System.Collections;using System.Windows.Forms;names
- 最近一个项目是一个基于winform的报告系统,根据一系列的查询参数计算出结果,最终生成一个格式规范的word文档,刚开始数据量不大(500
- 在SpringMVC的入门学习中,我发现@GetMapping注解的使用要注意路径冲突问题,在网上都没找到类似我这样的情况,所以我在这里将问
- 为什么要学习Android与H5互调?微信,QQ空间等大量软件都内嵌了H5,不得不说是一种趋势。Android与H5互调可以让我们的实现混合
- springMVC后台处理数组对象。list类型的参数,接收前台的数组值,实验了一下,结果还真可以。不用绑定到对象里面。当然我这个是前台传递
- 引言在 java8 中,您可以使用 Arrays.Stream 或 Stream.of 将 Array 转换为 Stream。1. 对象数组
- 前言 SpringCloud 是微服务中的翘楚,最佳的落地方案。 在微服务架构中多层服务之间会相互调用,如果其中有一
- Android获取系统内核版本的方法 &nbs
- 如题,市面上常见的方法是:var handle = bmp.GetHicon(); //得到图标句柄return Icon.Fr
- 在常见场景下:返回数据建议使用map,不建议使用实体对象 /** * 1. 名字包含雨并且年龄小于40