Alexander Lonberg Asked:2022-04-30 12:24:48 +0000 UTC2022-04-30 12:24:48 +0000 UTC 2022-04-30 12:24:48 +0000 UTC C# .NET 中存储的类实例属性的值在哪里? 772 我们有这个类: class Foo { public int Property => 123; } 如您所见,该属性仅getter且始终返回一个常量值 - 文字123。 如果创建 2 个或更多实例,值会被复制132,还是Property会指向同一个内存区域? 哪个选项会更便宜Foo或Bar? class Bar { private static readonly int _ConstValue = 123; public int Property => _ConstValue; } c# 1 个回答 Voted Best Answer aepot 2022-04-30T15:50:48Z2022-04-30T15:50:48Z 这个问题很简单。 首先,如果您像这样更改第二个示例: class Bar { private const int _ConstValue = 123; public int Property => _ConstValue; } 然后这两个类将在输出到一组相同的处理器指令时进行优化。 如您所知,属性是一组方法get,set在这种情况下,方法get_Property在使用常量时会这样编译。 mov eax, 0x7b ret 将一个常量写入 EAX 寄存器0x7b,即数字 123 并从方法返回。 这里的整个问题归结为字段和常量将如何不同static readonly,并且由于静态字段在应用程序执行期间仅初始化一次,因此从性能的角度来看,在初始化期间发生的情况绝对相同。 但是方法本身将如何改变get_Property- 它只会开始使用内存。 mov eax, [ecx+4] ret 将来自 ECX 寄存器地址的内存位置的值写入 EAX 寄存器,偏移量为 4 个字节。 当然,方法的代码会根据编译器可用的调用条件和优化而改变,但含义将保持不变。 结果:哪个更快,将存储单元写入处理器寄存器还是常量?绝对是一个常量,因为在这种情况下处理器根本不需要访问内存,常量的值已经在执行代码的缓存中。 但值得考虑的是,这两种指令都以闪电般的速度工作,并且只能从具体案例中感受到差异。换句话说,你不应该忘记常量而不是静态readonly字段,如果可能的话,使用它们。 如果您想知道文字和常量之间是否有区别,编译代码中没有区别。完全一样。区别仅在 C# 级别。
这个问题很简单。
首先,如果您像这样更改第二个示例:
然后这两个类将在输出到一组相同的处理器指令时进行优化。
如您所知,属性是一组方法
get,set在这种情况下,方法get_Property在使用常量时会这样编译。将一个常量写入 EAX 寄存器
0x7b,即数字 123 并从方法返回。这里的整个问题归结为字段和常量将如何不同
static readonly,并且由于静态字段在应用程序执行期间仅初始化一次,因此从性能的角度来看,在初始化期间发生的情况绝对相同。但是方法本身将如何改变
get_Property- 它只会开始使用内存。将来自 ECX 寄存器地址的内存位置的值写入 EAX 寄存器,偏移量为 4 个字节。
当然,方法的代码会根据编译器可用的调用条件和优化而改变,但含义将保持不变。
结果:哪个更快,将存储单元写入处理器寄存器还是常量?绝对是一个常量,因为在这种情况下处理器根本不需要访问内存,常量的值已经在执行代码的缓存中。
但值得考虑的是,这两种指令都以闪电般的速度工作,并且只能从具体案例中感受到差异。换句话说,你不应该忘记常量而不是静态
readonly字段,如果可能的话,使用它们。如果您想知道文字和常量之间是否有区别,编译代码中没有区别。完全一样。区别仅在 C# 级别。