.NET record使用with表达式复制未调用构造函数的疑问
关于.NET Record 类型
with 表达式未触发构造函数的问题解答 这个矛盾的本质是C#编译器的合规优化和默认生成代码的语义差异,具体原因可以拆解为三点:
- 你反编译看到的
<Clone>$()方法调用复制构造函数的逻辑,是编译器为record生成的默认未优化实现,仅在没有触发编译器优化条件时才会按这个逻辑执行。 - 微软官方文档描述的「先调用
<Clone>$()再赋值」是with表达式的标准语义,不是强制的实现要求:只要最终运行结果和标准语义完全一致,编译器可以任意调整实现逻辑。 - 你测试时未触发构造函数,符合以下两个优化触发条件的任意一种:
- 你的record没有自定义复制构造函数,自动生成的复制构造函数仅做简单的字段/属性拷贝,编译器在Release模式下会直接内联并消除构造函数调用,改为直接在托管堆上分配实例后逐字段拷贝原始值,再修改
with指定的属性,整个过程不会触发构造函数的调用入口。 - 你使用的是
record struct(值类型record),值类型的with表达式默认会直接做栈内存拷贝,完全不会调用构造函数。
- 你的record没有自定义复制构造函数,自动生成的复制构造函数仅做简单的字段/属性拷贝,编译器在Release模式下会直接内联并消除构造函数调用,改为直接在托管堆上分配实例后逐字段拷贝原始值,再修改
验证逻辑
你可以给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
相关产品推荐
相关产品推荐

