C#中的析构函数

C#—构造函数和析构函数 一、前言         作为比C更先进的语言,C#提供了更好的机制来增强程序的安全性,C#编译器具有严格的类型安全检查功能,它几乎能找出程序中所有的语法问题,但是程序通过了编译检查并不表示错误已经不存在了,不少难以察觉的程序错误是由于变量没有被正确初始化或清除造成的,而初始化和清除工作很容易被人遗忘。微软利用面向对象的概念在设计C#语言时充分考虑了这个问题并很好地予以解决:把对象的初始化工作放 阅读详情

引言

 

    在企业应用开发世界,性能,灵活性和安全性是最重要的。我作为一个VC++程序员开始我的职业生涯,并且在一个晴朗的早晨,我被转到了Web开发部。像每个C++程序员一样,我也很失落。我想每个像Tom,Dick甚至Harry能用HTML编程。然而,不久我就发现真正的挑战是生产高性能的,灵活的可靠的应用程序。综上所述,Web环境松耦合的,不分国界的本质将使你永远神往。

    为了制作高性能的灵活的应用程序,用最优化的方式使用你的资源是至关重要的。一个技巧是尽可能晚地使用你的资源并且在使用后尽快释放它。我在这里的意图是描述在C#中的对象清除机制。

解构器

    我们知道,‘解构器’被用来清除类的事例。当我们在C#中使用解构器是,我们必须记住以下几点:

  • 一个类只能有一个解构器。
  • 解构器不能被继承或重载。
  • 解构器不能被调用。他们是自动被(编译器)调用的。
  • 解构器不能带修饰或参数。

下面是类MyClass解构器的一个声明:

 

~ MyClass()   
{  
   // Cleaning up code goes here  

}

 

   

程序员不能控制解构器何时将被执行因为这是由垃圾收集器决定的。垃圾收集器检查不在被应用程序使用的对象。它认为这些条件是符合清楚的并且收回它们的内存。解构器也在程序退出时被调用。当解构器执行时其背后所发生的那一幕是解构器隐式调用对象基类的Object.Finalize方法。因此上述解构器代码被隐含转化成:

 

protected override void Finalize()  
{  
   try  
   {  
      // Cleaning up .  
   }  
   finally  
   {  
      base.Finalize();  
   }
}

    现在,让我们看一个解构器怎样被调用的例子。我们有三个类A,B和C 。B派生自A,C派生自B。每个类有它们自己的构造器和解构。在类App的main函数中,我们创建C的对象。

 

using System;  
class A  
{  
 public A()  
 {  
  Console.WriteLine("Creating A");  
 }  
 ~A()  
 {  
  Console.WriteLine("Destroying A");  
 }  
}  
   
class B:A  
{  
 public B()  
 {  
  Console.WriteLine("Creating B");  
 }  
 ~B()  
 {  
  Console.WriteLine("Destroying B");  
 }  
   
}  
class C:B  
{  
 public C()  
 {  
  Console.WriteLine("Creating C");  
 }  
   
 ~C()  
 {  
  Console.WriteLine("Destroying C");  
 }  
}  
class App  
{  
 public static void Main()  
 {  
  C c=new C();  
  Console.WriteLine("Object Created ");  
  Console.WriteLine("Press enter to Destroy it");  
  Console.ReadLine();  
  c=null;  
  //GC.Collect();  
  Console.Read();  
 }  
}
  

    正如我们预料的,基类的构造器将会被执行并且程序会等待用户按‘enter’。当这个发生,我们把类C的对象置为null.但解构器没有被执行..!!??正像我们所说的,程序员无法控制解构器何时被执行因为这是由垃圾搜集器决定的。但程序退出时解构器被调用了。你能通过重定向程序的o/p到文本文件来检查这个。我将它输出在这里。注意到基类的解构器被调用了,因为在背后base.Finalize()被调用了。

 

Creating A
Creating B
Creating C
Object Created 
Press enter to Destroy it
Destroying C
Destroying B
Destroying A
 

    所以,如果一旦你使用完对象你就想调用解构器,你该怎么做?有两个方法:

  • 调用垃圾搜集器来清理。

  • 实现IDisposable的Dispose方法。

 

调用垃圾搜集器

 

    你能通过调用GC.Collect方法强制垃圾搜集器来清理内存,但在大多数情况下,这应该避免因为它会导致性能问题。在上面的程序中,在GC.Collect()处移除注释。编译并运行它。现在,你能看到解构器在控制台中被执行了。

 

实现IDisposable接口

 

    IDisposable 接口包括仅有的一个公共方法,其声明为void Dispose()。我们能实现这个方法来关闭或释放非托管资源如实现了这个接口的类事例所控制的文件,流,和句柄等。这个方法被用做所有任务联合对象的资源释放。当实现了这个方法,对象必须寻求确保所有拥有的资源被继承结构中关联的资源也释放(不能把握,翻不出来)。

 

class MyClass:IDisposable  
{  
    public void Dispose()  
 {  
  //implementation  
 }  

}

 

    当我们实现了IDisposable接口时,我们需要规则来确保Dispose被适当地调用。

 

联合使用解构器和IDisposable接口

 

Public class MyClass:IDisposable  
{  
 private bool IsDisposed=false;  
 public void Dispose()  
 {  
  Dispose(true);  
  GC.SupressFinalize(this);  
 }  
 protected void Dispose(bool Diposing)  
 {  
  if(!IsDisposed)  
  {  
  if(Disposing)  
  {  
   //Clean Up managed resources  
  }  
  //Clean up unmanaged resources  
 }  
 IsDisposed=true;  
 }  
 ~MyClass()  
 {  
  Dispose(false);  
 }  

}

    在这里重载了Dispose(bool)来做清理工作,并且所有的清理代码都仅写在这个方法中。这个方法被解构器和IDisposable.Dispose()两着调用。我们应该注意Dispose(bool)没有在任何地方被调用除了在IDisposable.Dispose()和解构器中。

    当一个客户调用IDisposable.Dispose()时,客户特意地想要清理托管的和非托管资源,并且因此完成清理工作。有一件你必须注意的事情是我们在清理资源之后立即调用了GC.SupressFinalize(this)。这个方法通知垃圾搜集器不需要调用解构器,因为我们已经做了清理。

    注意上面的例子,解构器使用参数false调用Dispose。这里,我们确信垃圾搜集器搜集了托管资源。我们仅仅做非托管资源的清理。

 

结论

 

    尽管如此我们花费一些时间实现IDisposable接口,如果客户不能合适地调用它们会怎样?为此C#有一个酷的解决方案。‘using’代码块。它看起来像这样:
using (MyClass objCls =new MyClass())  
{  
   
}
 

    当控制从using块通过成功运行到结束或者抛出异常退出时,MyClass的IDispose.Dispose()将会被执行。记住你例示的对象必须实现System.IDisposable接口。using语句定义了哪个对象将被清除的一个范围。
基于Landsat-8数据的山西省吕梁市地表温度反演研究过程(大气校正法) 1.数据下载:本实验采用的数据是 ①从地理空间数据云下载的来自landsat8 卫星,云量<=1%,时间为2017年5月12日的山西省吕梁市影像数据。为全面覆盖吕梁市,选用了两片影像。 ②吕梁市边界矢量图 2.数据预处理 ... 阅读详情

相关推荐

Aurora8b10b光口通信实战:复位时序与IP核配置详解

本文深入解析了Aurora 8B10B协议在FPGA高速光口通信中的核心实践,重点剖析了确保链路稳定启动的关键复位时序与IP核配置细节。通过详解全双工与单工模式下的复位流程、Vivado中IP核的物理层与链路层参数设置,并结合用户逻辑设计实例,为工程师实现可靠的高速数据传输提供了清晰的实战指南。

weixin_29280219的博客 178

C#解构器

在C#中,解构器(Deconstructors)是一种特殊的方法,用于将对象的成员分解为多个独立的变量。通过定义解构器,您可以方便地从对象中提取和使用其属性或字段的值。使用解构器可以方便地从对象中提取和使用其属性或字段的值,使代码更加简洁和可读。然后,我们可以直接使用这些变量,无需通过对象访问成员。然后,我们在类中定义了一个解构器。对象,并使用解构器将其成员分解为。在上述示例中,我们定义了一个。在主程序中,我们创建了一个。

ultramand的博客,重生之我在cad上二次开发猛猛敲C#代码~ 792

从零到英雄:Spring Boot 微服务架构全攻略

在数字化转型的时代,微服务架构已成为构建可扩展、高可用系统的首选方案。本文以“从零到英雄”为主题,详细指导读者使用Spring Boot快速构建微服务帝国。从基础环境搭建入手,逐步深入到服务发现、配置管理、负载均衡、断路器、API网关、安全认证、监控与部署等核心模块。通过大量代码示例和详细解释,包括中文注释,帮助初学者和中级开发者掌握Spring Boot的核心概念和技术实践。文章强调实际操作,涵盖RESTful API开发、数据库集成、容器化部署等内容,并讨论常见问题与优化策略。无论你是Java开发者还是

一个被知识诅咒的人 2701

C# Deconstruct详解

C# Deconstruct 解构函数

鲤籽鲲的博客 1624

OSPF路由协议配置

构建直连连通让R1、R2、R3、R4加入OSPF,实现全网互通。掌握OSPF邻居状态的解读。掌握单区域OSPF的配置。理解OSPF的基本概念。AR3上的OSPF配置。AR4上的OSPF配置。R1上的OSPF配置。R2上的OSPF配置。

SURTR999的博客 7697

基于51单片机的多功能智能路灯控制系统(仿真+代码+原理图)

智能路灯控制系统主要由51单片机最小系统+1602显示模块+DS1302时钟模块+光强检测模块+按键输入模块+声光报警模块+LED照明模块+状态检测电路+人体车辆红外检测模块组成。能实现以下功能: 1.能够按键设定系统时间、工作时间、光照阈值 2.工作时间内路灯点亮,凌晨12点后路灯关闭,有人或车通过是,路灯点亮10s 3.非工作时间光照强度低于阈值,路灯点亮 4.能够检测系统工作状态,路灯应亮未亮,声光报警 5.具备手动控制,能够切换自动/手动控制功能

u012759563的博客 8181

C#中的垃圾回收、资源清理及推迟初始化

垃圾回收是运行时的核心功能,旨在回收不再被引用的对象所占用的内存,并不会处理如数据库连接、句柄(文件、窗口等)、网络端口及硬件设备。此外,垃圾回收器根据是否存在引用来决定要清理什么,处理的是引用对象,并且只回收堆上的内存。如果维持一个对象的引用,就会阻止垃圾回收器回收对象所占用的内存。.Net垃圾回收器采用的是mark-and-compact算法(首先确定所有可达对象,然后移动这些对象,使它们紧挨着存放,有点类似于磁盘碎片整理)。一次垃圾回收周期开始时,垃圾回收器会识别出对象的所有根引用,然后遍历根引用所标

夜槿笙歌的博客 1938

基于 Simulink 的三相四线制整流器在三相不平衡负载下的中点电位平衡控制实战教程。

本文介绍了三相四线制整流器在不平衡负载下的中点电位平衡控制方法。首先分析了中点电位漂移的物理机理和控制策略(零序电压注入)。接着详细讲解了Simulink建模步骤:搭建三相四线制主电路、设计平衡控制算法、实现PWM调制。通过对比有无平衡控制的仿真结果,验证了控制方法的有效性。最后提供了工程建议:零序注入需限幅、考虑中性线寄生电感影响、采用稳健的PI参数。该方案能有效抑制中点电位波动,保障三电平系统在不平衡工况下的稳定运行。

MHD0815的博客 63

C#垃圾回收器GC、析构函数(Finalize 方法)和Dispose

以应用程序的root为基础,遍历应用程序在Heap上动态分配的所有对象,通过识别它们是否被引用,来确定哪些对象是已经死亡的,哪些仍需要被使用。但你的代码中还是可以使用.NET Framework中GC的某些方法进行手动回收,前提是必须要深刻理解GC的回收原理,否则手动调用GC在特定场景下很容易干扰到GC的正常回收甚至引入不可预知的错误。:不能在析构函数中释放托管资源,因为析构函数是由垃圾回收器调用的,可能在析构函数调用之前,类包含的托管资源已经被回收了,从而导致无法预知的结果。与析构函数的区别主要是,

风清扬的专栏 1555

【FreeSwitch开发实践】外呼网关配置(拨打电话)

FreeSwitch开发一个重要应用是外呼,所谓外呼就拨打真实电话或手机号呼叫,配合语音机器人可以实现智能客服的功能。外呼配置主要是配置外呼服务器,外呼服务器主要指SIP网关,每个外呼服务器就是一个SIP节点,FreeSwitch服务也可以是一个SIP节点。本文主要介绍了FreeSwitch外呼相关配置,主要有外呼配置的模式,包括注册模式和非注册模式网关加载的查看方法拨号中常见的呼出配置和呼入配置如果觉得有些帮助或觉得文章还不错,请关注一下博主,你的关注是我持续写作的动力。............

xiao2macf的专栏 1万+

抑制电磁干扰(EMI)的实用电路技术

抑制电磁干扰(EMI)的实用电路技术 qtFK_EMC_EMI 【导读】本系列文章的第 1 部分至第 4 部分详细介绍了开关电源稳压器引起的传导发射和辐射发射,包括噪声产生机制、测量要求、频率范围、适用的测试限值、传播模式和寄生效应。在第 5 部分中,我将基于这一理论基础介绍抑制电磁干扰 (EMI) 的实用电路技术。 一般来说,电路原理图和印刷电路板 (PCB) 对于实现出色的 EMI 性能至关重要。第 3 部分重点强调通过谨慎的元器件选型和 PCB 布局尽量减小“功率回路”寄生电感的重要性。电源转换

学海无涯的专栏 1196

【C# 教程系列第 8 篇】什么是 c# 中的析构函数

什么是析构函数?析构函数是以 “~” 开头的

“Allen Su”的博客 1966

概率的接力:拆解大模型“预测下一个词“的底层逻辑

大模型的智能不在于它拥有了意识,而在于它用纯数学的架构,将人类语言的复杂结构压缩为可计算的向量轨迹与概率接力。当我们不再将其拟人化为"思考者",而是视作高维条件概率引擎时,才能真正驾驭它。预测下一个词,从来不是终点,而是起点。未来的核心竞争力,属于那些能洞察其统计本质、善用其模式生成能力,并以人类理性与事实为锚点的协作者。词元的轨迹终会止步于上下文窗口,但对技术底层的清醒认知,才是跨越幻觉、走向真实智能的基石。

AI浩 333

C#之析构函数,详细讲解。

可以定义在垃圾回收程序最终销毁对象之前调用的方法,该方法称为析构函数。 什么意思呢?我平常用的比较多的都是构造函数,因为我们每次new一个对象,程序就会自动调用对象中的构造函数,从而给对象动态的开辟一块内存。 但是有没有想过,内存没用完,怎么办,得有回收机制,去回收空闲的内存。 好家伙,C#有自己的垃圾回收机制。这个的’垃圾’包含空闲内存,不需要程序员手动去释放空间,人家是自动的,但是有一点不好的是!他这个自动是随机的,不是你每次运行程序他就必须回收,他是看心情-,- 有可能你运行10次 它心情好,10

csdn2990的博客 4772

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

c#中的析构函数

用于在对象被销毁时执行清理操作。它与构造函数相反,构造函数用于在对象创建时执行初始化操作。

qq_35624605的博客 952

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C#析构函数

一、C#析构函数 1. 析构函数的定义与注意的问题 析构函数用于释放被占用的系统资源。 析构函数的名字由符号“~”加类名组成。 使用析构函数时,应该注意下面的问题: ?只能在类中使用析构函数,不能在结构中使用析构函数。 ?一个类只能有一个析构函数。 ?不能继承或重载析构函数。 ?析构函数只能被自动调用。 ?析构函数没有任何修饰符、没有任何参数、也不返回任何值。 2. ...

adiking520110的博客 642

C#析构函数 (转载)

一、C#析构函数 1. 析构函数的定义与注意的问题析构函数用于释放被占用的系统资源。析构函数的名字由符号“~”加类名组成。使用析构函数时,应该注意下面的问题: 只能在类中使用析构函数,不能在结构中使用析构函数。 一个类只能有一个析构函数。 不能继承或重载析构函数。 析构函数只能被自动调用。 析构函数没有任何修饰符、没有任何参数、也不返回任何值。 2. 调用...

davy57345的博客 836

C# 析构函数

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _0702_析构函数 { class Program { static void Main(string[] a...

21号先锋者 1852
上一篇: DataGrid技巧大集合
下一篇: 数据库的连接串
AllenTing
博客等级 码龄22年 2粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值