# 构造函数 概念: - 构造函数用于在对象创建时做初始化 - 构造函数名必须和类名相同 - 构造函数没有返回值类型 - ==可以重载== 通常用法: - 给字段或属性设置初始值 - 保证对象一创建出来就处于可用状态 语法: ```csharp 访问修饰符 类名(参数列表) { } ``` 案例: ```csharp class Person { public string Name; public int Age; public Person() { Name = "默认值"; Age = 0; } public Person(string name, int age) { Name = name; Age = age; } } ``` `this` 调用其他构造函数: ```csharp class Person { public string Name; public int Age; public Person() : this("默认值", 0) { } public Person(string name, int age) { Name = name; Age = age; } } ``` 注意: 1. ==如果类里完全没写任何实例构造函数,编译器才会自动补一个无参构造函数== 2. ==只要你自己写了任意实例构造函数,默认无参构造函数就不会再自动生成== 3. 构造函数通常写 `public`,但也可以根据设计写成 `private` / `protected` 4. 子类构造函数可以通过 `base(...)` 调用父类构造函数 ---- # 析构函数 概念: - C# 里的析构函数更准确地说是==终结器(finalizer)== - 当对象即将被 GC 回收时,运行时可能会调用它 - 它主要用于“兜底清理非托管资源” 语法: ```csharp class Person { ~Person() { // 清理代码 } } ``` 注意: 1. 析构函数只能写在==类==里,结构体不能写 2. 不能手动直接调用析构函数 3. 析构函数执行时机==不确定== 4. 大多数业务代码里==不推荐为了练习而滥写析构函数== 5. 现代 .NET 中,更常见的做法是优先使用 `IDisposable`、`using` 和 `SafeHandle` ---- # 垃圾回收 垃圾回收(GC): - GC 是 .NET 的自动内存管理机制 - 它负责识别哪些托管对象还“活着”,哪些已经不可达,可以回收 基础理解: 1. 只要对象还能从“根”访问到,就一般不会被回收 2. 访问不到的对象,才有机会被 GC 回收 3. GC 主要管理的是==托管堆上的对象== 分代概念: - .NET GC 常分为 0、1、2 代 - 新对象一般先进入 0 代 - 活得越久,越可能被提升到更高代 - 大对象通常会进入 LOH(大对象堆),阈值常见记法是 >= `85,000` 字节 注意: 1. ==`GC.Collect()` 一般不建议手动乱调== 2. 手动触发 GC 可能带来性能抖动 3. “值类型一定在栈上、引用类型一定在堆上”不是绝对规则 4. GC 解决的是==托管内存==问题,不等于所有资源都会自动及时释放 ---- # GC 和 IDisposable 首先区分资源类型: - **托管资源** 比如普通对象、字符串、集合。主要由 GC 管理。 - **非托管资源** 比如文件句柄、数据库连接、Socket、窗口句柄。需要更及时地手动释放。 为什么要用 `IDisposable`: - 因为 GC 只负责“对象内存”回收 - 但像文件、连接、句柄这类资源,经常需要你主动关闭 最常见写法: ```csharp using var stream = new FileStream("demo.txt", FileMode.OpenOrCreate); // 使用 stream ``` 说明: - `using` 结束时会自动调用 `Dispose()` - 这比“等 GC 什么时候想起来再收”更可靠 标准释放模式示意: ```csharp public class MyResource : IDisposable { private bool _disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { // 释放托管资源 } // 释放非托管资源 _disposed = true; } ~MyResource() { Dispose(false); } } ``` 补充理解: 1. `Dispose()` 是“我现在就主动释放” 2. 析构函数是“万一你忘了,我最后帮你兜底一次” 3. `GC.SuppressFinalize(this)` 的意思是: 这个对象已经手动释放好了,不用再走终结器那一套 复习重点: - GC 管托管内存 - `Dispose` 管需要及时释放的资源 - 最常用姿势不是手写 `GC.Collect()`,而是优先写好 `using` / `Dispose` #封装 #核心