You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中在类的析构函数中使用new()的效果探究

析构函数中创建实例未引发StackOverflowException反而终止的原因分析

我做了个学术实验,想搞明白为什么程序会正常终止,而不是抛出StackOverflowException。我只在类的析构函数/终结器里创建新实例,原本以为代码会像while(true)循环一样永久运行。相关代码和运行输出如下:

实验代码

class Animal
{
    static int i = 0;
    public Animal()
    {
        Animal.i = Animal.i + 1;
        Console.WriteLine(i + " Object created.." );
    }

    ~Animal()
    {
        new Animal();
    }

}
internal class Program
{
    static void Main(string[] args)
    {
        Animal a = new Animal();
    }

}

运行输出示例

运行1输出:

76727 Object created..
76728 Object created..
76729 Object created..
Press any key to continue . . .

运行2输出:

76818 Object created..
76819 Object created..
76820 Object created..
76821 Object created..
Press any key to continue . . .

原因解析

这背后是.NET垃圾回收(GC)和终结器队列的工作机制在起作用:

  • 当Main方法执行完毕,第一个Animal实例失去引用,被GC标记为可回收。
  • GC处理该实例时,会将它的终结器放入终结器队列,由专门的终结器线程执行。
  • 终结器线程执行~Animal()时创建新的Animal实例,这个新实例后续也会被GC处理并触发终结器,看似形成循环,但实际有几个关键限制:
    1. .NET的终结器线程执行受GC调度,CLR会限制终结器的执行次数,避免无限循环耗尽系统资源。当内存使用达到阈值,GC会调整策略,不再继续处理新的终结器请求。
    2. 主线程已经结束(Main执行完成),GC在后台处理终结器,但当没有更多根引用,且终结器队列的处理达到一定限度后,CLR会直接终止程序,不会让循环无限进行。
  • 这和while(true)这种在主线程的同步循环完全不同,终结器执行在后台线程,受CLR资源管理策略约束,所以不会无限运行,最终程序正常终止。

内容的提问来源于stack exchange,提问作者Sekhar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:32:50