使用with关键字复制record struct时重新初始化只读属性
问题:只读记录结构体使用
with关键字时派生属性未重新初始化 我定义了一个只读记录结构体readonly record struct FooRecord,它包含一个从构造函数参数Foo派生的只读属性SomeDerivedProperty:
public readonly record struct FooRecord(string Foo) { public IList<string> SomeDerivedProperty { get; } = Foo.Split('.').ToList(); }
当使用with关键字复制该记录结构体时,新实例的只读属性并未重新初始化:
FooRecord record1 = new("Hello.World"); FooRecord record2 = record1 with { Foo = "A.B.C" }; Debug.WriteLine(string.Join(".", record2.SomeDerivedProperty)); // 输出 "Hello.World" 而非 "A.B.C"
请问是否有方法让新记录结构体在分配新的构造函数参数值后,重新初始化该只读属性?
解决方案
方法1:改为只读计算属性(推荐)
既然SomeDerivedProperty完全依赖于Foo的值,直接将其改为只读计算属性,每次访问时都会基于当前的Foo重新生成结果,从根源上避免with操作带来的不一致问题:
public readonly record struct FooRecord(string Foo) { public IList<string> SomeDerivedProperty => Foo.Split('.').ToList(); }
修改后,使用with更新Foo值后,访问SomeDerivedProperty会自动基于新的Foo生成分割列表,输出结果即为A.B.C对应的["A", "B", "C"]。
方法2:自定义复制方法替代with
如果需要缓存派生属性的计算结果(比如计算成本较高),可以自定义一个复制方法,确保新实例的派生属性基于新的Foo重新初始化:
public readonly record struct FooRecord(string Foo) { public IList<string> SomeDerivedProperty { get; } = Foo.Split('.').ToList(); public FooRecord WithFoo(string newFoo) { return new FooRecord(newFoo); } }
使用时直接调用该方法替代with:
FooRecord record2 = record1.WithFoo("A.B.C");
方法3:手动控制构造与解构逻辑
记录结构体的with操作本质是解构原实例成员、修改指定值后再调用构造函数。我们可以手动实现解构方法,并显式定义构造逻辑,确保派生属性始终与当前Foo同步:
public readonly record struct FooRecord(string Foo) { public IList<string> SomeDerivedProperty { get; } public FooRecord(string foo, IList<string> someDerivedProperty) : this(foo) { SomeDerivedProperty = someDerivedProperty ?? foo.Split('.').ToList(); } public void Deconstruct(out string foo, out IList<string> someDerivedProperty) { foo = Foo; someDerivedProperty = SomeDerivedProperty; } }
这种方法需要额外维护构造和解构逻辑,适合复杂场景下的自定义控制。
内容的提问来源于stack exchange,提问作者Vg0
相关产品推荐
相关产品推荐

