在 C# 中,“类的对象的生命周期”是指从对象被创建(分配内存、初始化)到它被垃圾回收器(GC)回收、内存被释放的整个过程。理解这个过程,对写出高性能、无内存泄漏的程序非常关键。
✅ 一句话总结:
对象的生命周期 = 创建 → 使用 → 不再被引用 → GC 标记 → 回收 → 内存释放
🔍 分阶段详解:
🧠 关键概念补充:
✅ GC Roots 包括:
全局静态变量
当前线程栈上的局部变量
CPU 寄存器中的引用
正在使用的
GCHandle
⚠️ 注意:
GC 是非确定的:你无法预测对象什么时候被回收。
Finalizer 不保证及时执行:不要依赖它来释放关键资源。
推荐使用
Dispose()模式(即IDisposable)来释放非托管资源(如文件句柄、数据库连接)。
🧪 示例代码:
class MyClass : IDisposable
{
    public MyClass()
    {
        Console.WriteLine("对象创建");
    }
    ~MyClass() // 终结器(不推荐依赖)
    {
        Console.WriteLine("终结器被调用");
    }
    public void Dispose()
    {
        Console.WriteLine("Dispose 被调用");
        GC.SuppressFinalize(this); // 告诉 GC 不用再调用终结器
    }
}
class Program
{
    static void Main()
    {
        MyClass obj = new MyClass();
        obj.Dispose(); // 手动释放资源
        obj = null; // 取消引用
        GC.Collect(); // 强制触发 GC(仅用于测试)
        GC.WaitForPendingFinalizers();
        Console.WriteLine("程序结束");
    }
}✅ 总结一句话(面试可用):
C# 中对象的生命周期由 CLR 管理,从
new创建开始,到不再被任何根引用后,由 GC 在某个不确定时间点回收内存;非托管资源应通过IDisposable显式释放。
如果你有具体场景(比如:内存泄漏、Dispose 没调用、GC 不回收等),我可以帮你分析。
下面给出一段最小可运行的 C# 控制台程序,把“对象的一生”全部打印出来。 代码里每行都加了中文标注,运行后屏幕上的输出就是生命周期的时间线。
using System;
namespace LifeCycleDemo
{
    // 1. 定义一个“会说话”的类,方便我们观察每一步
    class DemoObject : IDisposable
    {
        private readonly string _id;
        // 构造阶段:对象诞生
        public DemoObject(string id)
        {
            _id = id;
            Console.WriteLine($"【构造】   {_id} 对象在托管堆上分配,构造函数执行完毕。");
        }
        // 模拟“干活”
        public void DoWork()
        {
            Console.WriteLine($"【使用】   {_id} 正在干活,this={GetHashCode()}");
        }
        // 显式释放资源(IDisposable 接口)
        public void Dispose()
        {
            Console.WriteLine($"【Dispose】{_id} 被显式释放,非托管资源已清理。");
            GC.SuppressFinalize(this); // 告诉 GC“别再跑终结器”
        }
        // 终结器(Finalizer)—— 备胎,万一忘记 Dispose
        ~DemoObject()
        {
            Console.WriteLine($"【终结器】 {_id} 被终结,对象即将被回收。");
        }
    }
    class Program
    {
        static void Main()
        {
            Console.WriteLine("=== 对象生命周期演示开始 ===\n");
            // 2. 创建:new 导致在托管堆分配
            DemoObject obj = new DemoObject("A1");
            obj.DoWork();          // 3. 使用
            // 4. 主动 Dispose,释放非托管资源
            obj.Dispose();
            // 5. 断开引用:对象变成“不可达”
            obj = null;
            // 6. 强制 GC(仅演示用,生产代码不要这么写)
            Console.WriteLine("\n【GC】     强制触发垃圾回收...");
            GC.Collect(0, GCCollectionMode.Forced, blocking: true, compacting: true);
            GC.WaitForPendingFinalizers(); // 等终结器跑完
            Console.WriteLine("\n=== 对象生命周期演示结束 ===");
        }
    }
}把文件保存为 LifeCycleDemo.cs,编译运行:
dotnet run典型输出(已对齐):
=== 对象生命周期演示开始 ===
【构造】   A1 对象在托管堆上分配,构造函数执行完毕。
【使用】   A1 正在干活,this=54267266
【Dispose】A1 被显式释放,非托管资源已清理。
【GC】     强制触发垃圾回收...
=== 对象生命周期演示结束 ===注意: 由于我们在 Dispose() 里调用了 GC.SuppressFinalize(this),终结器不会执行,所以看不到“【终结器】”这一行。 如果把 Dispose() 那行注释掉再运行,就能观察到“【终结器】”输出,证明对象真的被 GC 回收了。
这样,“创建 → 使用 → 显式释放 → 失去引用 → GC 回收” 整个生命周期就完整跑通并打印出来了。