假设我有一个与以下课程有关的课程: const
private const decimal x = 2.0m;
只读字段
private readonly decimal y = 2.0m;
具有此签名的方法
void Method1(in decimal x)
如果我使用const x Method1(x)调用Method1,我假设x的值将按值传递,而当我将Method1与只读y一起使用Method1(in y)时,该值将通过只读引用传递。因此,我的期望是,性能更高的是用作“伪” const的只读字段。我错了?我怀疑编译器内部将使用const或clr对其进行优化,以使其成为通过引用传递的只读字段而具有出色的性能。
答案 0 :(得分:2)
我已经进行了测试,获胜者是in传入的只读字段,这是使用i7 8700k处理器执行的代码
class Test
{
public const decimal x = 0.2m;
public readonly decimal y = 0.2m;
public void Method1(in decimal x)
{
Thread.MemoryBarrier();
}
}
class Program
{
static void Main(string[] args)
{
var t = new Test();
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < 100000000; i++)
{
t.Method1(in t.y);
}
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);
sw.Restart();
for (var i = 0; i < 100000000; i++)
{
t.Method1(Test.x);
}
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);
Console.ReadLine();
}
}
以t.Method1(在t.y中)调用的方法;消耗了11606428个s 作为t.Method1(Test.x);调用的方法;消耗了16963941滴答声
因此,在这种情况下,没有针对const进行优化
答案 1 :(得分:2)
是的,可能 readonly 选项的性能更高,但是对于是否将这种性能提升视为有意义的问题,仍有待商。
为什么?
const
版本实际上将在每次调用该方法时运行十进制构造函数,而readonly / in版本将仅将引用复制到以前创建的十进制实例。后者显然更快。
您可以通过简单地检查IL来验证这一点:
常量版本:
IL_0001: ldc.i4.s 20
IL_0003: ldc.i4.0
IL_0004: ldc.i4.0
IL_0005: ldc.i4.0
IL_0006: ldc.i4.1
IL_0007: newobj instance void [mscorlib]System.Decimal::.ctor(int32, int32, int32, bool, uint8)
IL_000c: call instance bool C::Method2(valuetype [mscorlib]System.Decimal)
只读版本:
IL_0002: ldflda valuetype [mscorlib]System.Decimal C::dd
IL_0007: call instance bool C::Method1(valuetype [mscorlib]System.Decimal&)
IL_000c: pop
也就是说,我不太确定为什么将const
与性能联系在一起。 const
是一种在代码中传达给定值永远不会改变的方法。 const
并不意味着,使用常量存储的此值将在使用时表现更好。
除非您确实有一个由经验证明的性能问题可以通过这种边际(最佳)优化解决,否则逻辑上为常数的值应为const
,而逻辑上为只读的变量值应为readonly
,所有其他注意事项均应忽略。如果您的案例是前者,那么请在代码中清楚地说明为什么将逻辑常数值实现为只读字段。