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

.NET为未构造完成对象调用终结器的相关技术疑问

C#构造函数执行失败后终结器仍被调用的问题解答

1. 该行为是否符合规范?

完全符合C#语言规范。只要对象的内存已经在托管堆上完成分配,哪怕构造函数执行抛出异常、对象未完全初始化,CLR仍会将其视为可终结对象,最终调用它的终结器。

2. 微软官方文档中是否有该机制的相关说明?

有明确说明。官方文档提到:当对象构造过程中抛出异常时,CLR依然会触发终结器。这是因为对象内存已被分配,构造函数执行期间可能已经初始化了部分非托管资源,需要通过终结器完成清理,避免资源泄漏。

3. 该现象产生的原因是什么?

CLR创建对象的流程分为两步:

  • 第一步:在托管堆上为对象分配内存,此时对象已经存在于堆中,拥有唯一的哈希标识;
  • 第二步:调用构造函数完成对象的初始化。

如果构造函数执行失败抛出异常,对象的内存并未被回收——它已经是堆上的有效对象,只是未完成初始化。GC扫描托管堆时,会识别出带有终结器的对象(无论构造是否完成),将其加入终结队列,最终执行终结器以清理可能已分配的资源。


测试代码

using System;

class TestFinalizer
{
    public TestFinalizer()
    {
        Console.WriteLine($"构造函数执行中,对象哈希码:{GetHashCode()}");
        // 模拟构造失败抛出异常
        throw new InvalidOperationException("构造函数执行失败");
    }

    ~TestFinalizer()
    {
        Console.WriteLine($"终结器被调用,对象哈希码:{GetHashCode()}");
    }
}

class Program
{
    static void Main()
    {
        try
        {
            new TestFinalizer();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"捕获异常:{ex.Message}");
        }
        // 强制触发GC并等待终结器执行
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

运行输出

构造函数执行中,对象哈希码:7880838
捕获异常:构造函数执行失败
终结器被调用,对象哈希码:7880838

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 22:34:55