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

.NET record使用with表达式复制未调用构造函数的疑问

关于.NET Record 类型 with 表达式未触发构造函数的问题解答

这个矛盾的本质是C#编译器的合规优化和默认生成代码的语义差异,具体原因可以拆解为三点:

  • 你反编译看到的<Clone>$()方法调用复制构造函数的逻辑,是编译器为record生成的默认未优化实现,仅在没有触发编译器优化条件时才会按这个逻辑执行。
  • 微软官方文档描述的「先调用<Clone>$()再赋值」是with表达式的标准语义,不是强制的实现要求:只要最终运行结果和标准语义完全一致,编译器可以任意调整实现逻辑。
  • 你测试时未触发构造函数,符合以下两个优化触发条件的任意一种:
    1. 你的record没有自定义复制构造函数,自动生成的复制构造函数仅做简单的字段/属性拷贝,编译器在Release模式下会直接内联并消除构造函数调用,改为直接在托管堆上分配实例后逐字段拷贝原始值,再修改with指定的属性,整个过程不会触发构造函数的调用入口。
    2. 你使用的是record struct(值类型record),值类型的with表达式默认会直接做栈内存拷贝,完全不会调用构造函数。

验证逻辑

你可以给record添加带自定义副作用的复制构造函数,此时编译器的优化会被阻断,with表达式就会按标准语义触发构造函数调用:

public record Person(string Name, int Age)
{
    protected Person(Person original)
    {
        // 自定义副作用会阻止编译器优化
        Console.WriteLine("复制构造函数执行");
        Name = original.Name;
        Age = original.Age;
    }
}

// 测试代码
var p1 = new Person("张三", 18);
var p2 = p1 with { Age = 20 };
// 此时会输出"复制构造函数执行"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:36:01