C#核心(5)构造,析构,垃圾回收

前言

也是有很长一段时间没有更新相关教程了,是因为十月份的taptap聚光灯比赛的缘故,作者几乎把精力全都放到了自己开发的项目上面,所以才没有更新博客,并不是不更新了。

上一节我们进行了对成员变量的讲解,既然有成员变量,那其实必然就会有成员方法,一个人他不可能只有属性,他还一定有技能。

在C#中,构造和析构函数以及垃圾回收起着重要的作用,它们有助于管理和释放内存资源。以下是它们的作用的解释:

  1. 构造函数(Constructor):构造函数是在创建类的实例(对象)时自动调用的特殊方法。它的主要作用是初始化对象的成员变量和执行其他必要的初始化操作。构造函数可以有参数,也可以是无参数的。它们通常被用来设置对象的初始状态,确保对象在被使用之前是可用的。

  2. 析构函数(Destructor):析构函数是类的特殊方法,用于在对象被销毁之前执行清理操作。它与构造函数相反,用于释放对象所占用的资源,如文件句柄、数据库连接、网络连接等。析构函数没有参数,且只能有一个。它在对象被垃圾回收之前被自动调用。

  3. 垃圾回收(Garbage Collection):垃圾回收是.NET Framework提供的一种自动内存管理机制。它的主要作用是自动释放不再使用的内存资源,避免内存泄漏和垃圾堆积的问题。垃圾回收器会周期性地扫描程序的堆内存,标记不再被引用的对象,并进行回收和整理。这种机制使得程序员不必手动释放内存,避免了常见的错误和内存泄漏的风险。

嗯,很抽象,没事,我慢慢带你了解。

构造函数

基本概念

在实例化对象时,调用来初始化的函数,你可以理解成,在对象生成时,这个函数会最先执行,将你想要执行的操作赋予给对象。

tips:如果不写,默认存在一个无参构造函数。

写法

  1. 没有返回值
  2. 函数名必须和类名相同
  3. 没有特殊情况,一般默认为public 
  4. 构造函数可以被重载
  5. this代表当前调用该函数自己

    tips:如果自己不实现无参构造函数而实现有参,默认失去无参构造

例子 

public class Person {private int age;private String name;public Person()//类中允许声明无参构造函数,结构体不允许{this.age ="ling1s";this.name = 18;}}

构造函数特殊写法

可以通过this重用构造函数的代码

示例:

public class MyClass
{private int value1;private int value2;// 构造函数1public MyClass() : this(0){}// 构造函数2,调用构造函数3public MyClass(int value) : this(value, 0){}// 构造函数3public MyClass(int value1, int value2){this.value1 = value1;this.value2 = value2;}
}

在上面的示例中,我们定义了三个构造函数:MyClass()MyClass(int value)MyClass(int value1, int value2)。构造函数1和构造函数2都通过使用this关键字调用了构造函数3,以避免重复的代码。

使用构造函数链可以创建多个不同参数的构造函数,以便在不同的情况下初始化对象的属性。也就是说你可以通过传不同的参数构造不同的属性。

析构函数

C#中存在垃圾回收机制GC,除非想在某一对象被垃圾回收时,做一些特殊处理,才会使用,但在unity开发中一般是不会使用的。

语法
~类名()
{
}

下面是一个示例代码,展示了C#中的析构函数的用法:

using System;public class MyClass
{private string name;public MyClass(string n){name = n;Console.WriteLine("对象 {0} 被创建。", name);}~MyClass(){Console.WriteLine("对象 {0} 被销毁。", name);}
}public class Program
{public static void Main(){MyClass obj1 = new MyClass("对象1");MyClass obj2 = new MyClass("对象2");obj1 = null;obj2 = null;GC.Collect();GC.WaitForPendingFinalizers();}
}

在上面的代码中,我们创建了一个名为MyClass的类,它有一个构造函数和一个析构函数。构造函数用来初始化对象,而析构函数在对象被销毁时执行一些清理工作。

Program类的Main方法中,我们创建了两个MyClass对象obj1obj2。然后,我们将这些对象设置为null,这样它们就不再被引用了,并且可以被垃圾回收器回收。

最后,我们调用GC.Collect()方法和GC.WaitForPendingFinalizers()方法,以确保垃圾回收器在我们退出程序之前运行,并且调用所有未调用的析构函数。在控制台输出中,我们可以看到析构函数被调用的消息。你可以自己尝试去试一下,因为在unity中几乎不使用,这里就不重点讲解了。

垃圾回收机制(GC)

垃圾回收机制的过程是在遍历堆(Heap)上动态分配的所有对象通过识别他们是否被引用来确定他们是不是垃圾,如果没被引用了,那就是垃圾,就应该释放。

tips:GC只负责Heap内存的垃圾回收,值类型在栈(stack)中分配,有自己的生命周期(到点就会噶),不用管理,会自动分配释放

C#中内存在回收机制中的大概原理:

在C#中,内存回收机制是由垃圾回收器(Garbage Collector)负责管理和释放不再使用的内存。垃圾回收器会自动扫描程序中的对象,找出不再被引用的对象,并将其标记为垃圾。随后,垃圾回收器会回收这些垃圾对象所占用的内存空间,并将其重新分配给新的对象。

为了更高效地管理内存,垃圾回收器将内存分为三代:0代内存、1代内存和2代内存。每个代表了对象的存活时间和垃圾回收的频率。

0代内存:当一个对象被创建时,它会被分配到0代内存中。0代内存是垃圾回收器会直接回收的内存区域,回收频率较高。通常情况下,如果一个对象在0代内存中存活一段时间,并且没有变成垃圾,它将被提升到1代内存。

1代内存:1代内存是相对于0代内存而言的。当一个对象在0代内存中存活一段时间后,垃圾回收器将会将其提升到1代内存中。1代内存的回收频率相对较低,因为在这里的对象通常能够更长时间地存在。

2代内存:2代内存是相对于1代内存而言的。当一个对象在1代内存中存活一段时间后,垃圾回收器将会将其提升到2代内存中。2代内存的回收频率最低,因为这里的对象通常是程序中存活时间最长的对象。

通过将内存分为不同的代,垃圾回收器能够更加有效地管理内存,提高程序的性能和效率。不同代的内存回收频率也是动态调整的,垃圾回收器会根据不同代的内存状态和使用情况,动态调整垃圾回收的频率和策略。

代的概念

代是垃圾回收机制使用的一个算法(分代算法,感兴趣可以了解一下),新分配的对象都会被配置在第0代内存中,每次分配都可能先进行GC,当0代内存存满了后。

C#中垃圾回收过程大概如下

博主自行整理如下:

  1. 标记对象,从跟(静态字段,方法参数)开始检查,标记可达对象,不可达就是垃圾

  2. 搬迁对象,压缩堆

  3. 释放未标记对象,修改引用地址(85000字节以上)

    tips:大对象被认为是二代内存,是为了提高性能。

gpt解释如下:

C#中的内存回收机制基于垃圾回收器(Garbage Collector, GC)。

  1. 对象创建:当程序创建一个对象时,垃圾回收器会在托管堆(Managed Heap)中为其分配内存空间。

  2. 引用跟踪:垃圾回收器会跟踪所有的引用类型对象,并在程序执行时检查这些对象是否仍然被活动的引用所使用。如果一个对象没有被任何活动的引用所引用,则被判定为垃圾对象。

  3. 垃圾标记:在托管堆中,垃圾回收器会标记所有的活动对象,并将它们标记为“非垃圾”。同时,未标记的对象则被认为是垃圾对象。

  4. 垃圾回收:一旦垃圾回收器完成了垃圾标记,它会在堆上进行垃圾回收操作。在回收过程中,垃圾回收器会从堆中删除垃圾对象,并释放它们所占用的内存空间。

  5. 内存整理:垃圾回收器还会执行内存整理操作,以消除堆中的内存碎片。内存整理可以提高内存的利用率,减少内存分配的开销。

需要注意的是,垃圾回收器的具体实现会因不同版本的.NET框架而有所差异。有时候,开发人员也可以手动控制垃圾回收的行为,例如通过调用GC.Collect()方法来强制进行垃圾回收。

手动方法

GC.Collect();//手动触发,一般不会频繁调用,都在游戏loading时调用

总结

这一节的内容比较干,理解起来比较困难,主要掌握构造函数的使用,对于析构和垃圾回收,做了解就好,如果是面向unity方向的话,这两个的使用频率不高,一般不是主要的知识点,但如果是面向.NET的工作,建议还是仔细翻看其他博主的文章或者相关教学视频。

另外,还是希望你多敲代码,不要只是看。

至此,与诸君共勉!

请期待我的下一篇博客!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/460751.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【隐私计算篇】全同态加密应用场景案例(隐私云计算中的大模型推理、生物识别等)

1.题外话 最近因为奖项答辩,一直在忙材料准备,过程非常耗费时间和精力,很难有时间来分享。不过这段时间虽然很忙碌,但这期间有很多新的收获,特别是通过与领域内专家的深入交流和评审过程,对密码学和隐私计算…

【汇编语言】第一个程序(四)—— 谁在幕后启动程序 : 探讨可执行文件的装载与执行

文章目录 前言1. 可执行文件的加载与运行1.1 DOS中的程序加载过程1.2 问题1:谁加载了1.exe?1.3 问题2:程序运行结束后的返回过程1.4 操作系统的外壳1.5 回答问题1和问题21.6 汇编程序执行的完整历程 2. 使用Debug加载与跟踪1.exe2.1 Debug的加…

Unreal Engine 5 C++(C#)开发:使用蓝图库实现插件(一)认识和了解Build.cs

目录 引言 一、创建一个C插件TextureReader插件 二、Build.cs文件 三、ModuleRules 四、TextureReader插件的构造 4.1ReadOnlyTargetRules的作用 4.2TextureReaderd的构造调用 4.3设置当前类的预编译头文件的使用模式 4.4PublicIncludePaths.AddRange与PrivateInclude…

SELS-SSL/TLS

一、了解公钥加密(非对称加密) 非对称加密中,用于加密数据的密钥与用于解密数据的密钥不同。私钥仅所有者知晓,而公钥则可自由分发。发送方使用接收方的公钥对数据进行加密,数据仅能使用相应的私钥进行解密。 你可以将…

STM32FreeRTOS 使用QSPI驱动nandFlash

STM32FreeRTOS 使用QSPI驱动nandFlash 不清楚为什么STM32同时打开3个以上的音频文件时会出现播放问题,所以更换方案。因为SRAM的内存空间过小,用于存储音频文件不适合,所以使用大小为128MByte的nandFlash。 nandFlash使用华邦的W25N01GVZEI…

vscode的一些使用心得

问题1:/home目录空间有限 连接wsl或者remote的时候,会在另一端下载一个.vscode-server,vscode的插件都会安装进去,导致空间增加很多,可以选择更换这个文件的位置 参考:https://blog.csdn.net/weixin_4389…

1Panel应用商店开源软件累计下载突破200万次!

2024年10月23日,1Panel应用商店内开源软件累计下载突破200万次。 1Panel(github.com/1Panel-dev/1Panel)是一款现代化、开源的Linux服务器运维管理面板,它致力于通过开源的方式,帮助用户简化建站与运维管理流程。 为…

基于MATLAB多参数结合火焰识别系统

一、课题介绍 本设计为基于MATLAB的火焰烟雾火灾检测系统。传统的采用颜色的方法,误识别大,局限性强。结合火焰是实时动态跳跃的,采用面积增长率,角点和圆形度三个维度相结合的方式判断是否有火焰。该设计测试对象为视频&#xf…

利用摄像机实时接入分析平台LiteAIServer视频智能分析软件进行视频监控:过亮过暗检测算法详解

视频监控作为一种重要的安全和管理工具,广泛应用于各个领域,如安全监控、交通监管、员工监管、公共场所监控等。然而,在实际应用中,视频监控系统经常面临各种挑战,其中之一便是视频画面过亮或过暗的问题。过亮过暗检测…

python画图|坐标轴比例设置方法

【1】引言 在前序学习进程中,我们通过ax.set_box_aspect()函数掌握了坐标轴等比例设置方法。 担当我在回顾以前的学习文章时,发现ax.axis()函数也可以设置坐标轴比例,比如下述文章,文章可通过点击链接直达: python画…

[前端][基础]JavaScript

1,JavaScript简介 JavaScript 是一门跨平台、面向对象的脚本语言,而Java语言也是跨平台的、面向对象的语言,只不过Java是编译语言,是需要编译成字节码文件才能运行的;JavaScript是脚本语言,不需要编译&…

用于文档理解的局部特征

本文介绍了一种名为DocFormerv2的多模态Transformer模型,它专为视觉文档理解(VDU)而设计。该模型可以处理视觉、语言和空间特征,利用编码器-解码器架构,并通过不对称地使用新颖的无监督任务进行预训练,以促…

Chromium127编译指南 Linux篇 - 额外环境配置(五)

引言 在成功获取 Chromium 源代码后,接下来我们需要配置适当的编译环境,以便顺利完成开发工作。本文将详细介绍如何设置 Python 和相关的开发工具,以确保编译过程无碍进行。这些配置步骤是开发 Chromium 的必要准备,确保环境设置…

HTTP相关返回值异常原因分析,第二部分

今天我们讲讲HTTP相关返回值异常如何解决(实例持续更新中) 一、4xx状态码 这些状态码表示请求有问题,通常是由于客户端的错误引起的。 1.1 400 Bad Request: 请求格式不正确,服务器无法理解。 状态码400的含义: …

.NET内网实战:通过白名单文件反序列化漏洞绕过UAC

01阅读须知 此文所节选自小报童《.NET 内网实战攻防》专栏,主要内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧,对内网和后渗透感兴趣的朋友们可以订阅该电子报刊,解锁更多的报刊内容。 02基本介绍 03原理分析 在渗透测试和红…

Spring Boot 实现文件分片上传和下载

文章目录 一、原理分析1.1 文件分片1.2 断点续传和断点下载1.2 文件分片下载的 HTTP 参数 二、文件上传功能实现2.1 客户端(前端)2.2 服务端 三、文件下载功能实现3.1 客户端(前端)3.2 服务端 四、功能测试4.1 文件上传功能测试4.2 文件下载功能实现 参考资料 完整案例代码&…

【数据结构】-数组

数组 特点: 数组的地址连续,可以通过下标获取数据。 1. 数组扩容 步骤: $1. 创建一个比原来数组更长的新数组 $2. 让原来数组当中的数据依次复制到新数组当中 $3. 让arr指向新数组,原数组空间释放 2. 数组插入 2.1 最后位置…

智慧小区:科技之光点亮幸福家园

智慧社区的未来发展方向与趋势 从智能化管理到便捷化服务,从环保节能到安全监控,智慧社区正以其前瞻性的视野和创新性的技术,引领着未来城市生活的新方向。从智慧社区的基本概念中通过运用现代科技手段,如物联网、云计算、大数据…

0,国产FPGA(紫光同创)-新建PDS工程

国产FPGA正在蓬勃发展,紫光同创FPGA是大家竞赛时经常遇到的一款国产FPGA,本专栏从IP核开始一直到后续图像处理等。 开发板:盘古50K标准板 1,新建PDS工程 点击File(1),然后是New Projects&#…