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

如何避免C# readonly record struct中的防御性副本?

关于readonly record struct防御性副本的疑问与验证

初始定义与原理解读

首先定义一个readonly record struct:

public readonly record struct S(int A, int B)
{
   
}

此前误以为record的位置参数会自动实现为属性,访问A和B会产生防御性副本,因此尝试手动定义readonly字段来规避:

public readonly record struct S(int A, int B)
{
   public readonly int A = A;
   public readonly int B = B;
}

此时A和B是字段,访问无副作用,且测试发现两种定义下编译器生成的record专属代码(相等性、哈希码生成等)一致。

补充测试与结论

后续补充了多层嵌套的测试代码:

const int SIZE = 10000;

var sw = new Stopwatch();
A[] aArray = new A[SIZE];
M[] mArray = new M[SIZE];
for(int repeat = 0; repeat < SIZE; repeat++) aArray[repeat] = new A(new(new(new(new(new(new(new(new(new(new(new(Random.Shared.Next()))))))))))));
for(int repeat = 0; repeat < SIZE; repeat++) mArray[repeat] = new M(new(Random.Shared.Next()));
int i = 0;
sw.Start();
for(int repeat = 0; repeat < SIZE; repeat++) i =+ aArray[repeat].B.C.D.E.F.G.H.I.J.K.L.I;
sw.Stop();
System.Console.WriteLine(i);
System.Console.WriteLine(sw.Elapsed);
sw.Reset();
sw.Start();
for(int repeat = 0; repeat < SIZE; repeat++) i =+ mArray[repeat].N.I;
sw.Stop();
System.Console.WriteLine(i);
System.Console.WriteLine(sw.Elapsed);

// 手动定义readonly字段的版本
readonly record struct A(B B){public readonly B B = B;}
readonly record struct B(C C){public readonly C C = C;}
readonly record struct C(D D){public readonly D D = D;}
readonly record struct D(E E){public readonly E E = E;}
readonly record struct E(F F){public readonly F F = F;}
readonly record struct F(G G){public readonly G G = G;}
readonly record struct G(H H){public readonly H H = H;}
readonly record struct H(I I){public readonly I I = I;}
readonly record struct I(J J){public readonly J J = J;}
readonly record struct J(K K){public readonly K K = K;}
readonly record struct K(L L){public readonly L L = L;}
readonly record struct L(int I){public readonly int I = I;}
readonly record struct M(N N){public readonly N N = N;}
readonly record struct N(int I){public readonly int I = I;}

// 自动生成属性的版本
readonly record struct A(B B){}
readonly record struct B(C C){}
readonly record struct C(D D){}
readonly record struct D(E E){}
readonly record struct E(F F){}
readonly record struct F(G G){}
readonly record struct G(H H){}
readonly record struct H(I I){}
readonly record struct I(J J){}
readonly record struct J(K K){}
readonly record struct K(L L){}
readonly record struct L(int I){}
readonly record struct M(N N){}
readonly record struct N(int I){}

重新测试后发现两种定义的耗时相近,此前的理解有误,两种情况均不会产生防御性副本。

核心疑问

  • 是否存在更优方式避免record的防御性副本?
  • 手动定义所有readonly字段繁琐且易出错,有没有对应的C#语法可以简化这个操作?
  • 若对防御性副本及record代码生成的理解仍有错误,请予以纠正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:15:24