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