【发布时间】:2016-01-15 00:33:24
【问题描述】:
我们知道很多关于常量的事情:
- 值必须在编译时已知
- 值永远不能在运行时更改
- 它们被推送到声明程序集元数据中
- 所有出现都被其在 IL 中的值替换
- 它们可能会造成严重的跨程序集版本控制问题
- 它们不消耗动态内存,因为它们的值在 IL 代码中被替换
- 常量只能是原始类型 + 任何初始化为 null 的引用类型(MSDN 没有提到这部分)
除了常量的基本特征之外,为什么 clr 团队决定用文字代替常量值的每次出现?在我看来,抖动将完全能够将包含的程序集加载到内存中,在元数据中搜索类型并提取正确的最新值。
我真的不相信这里的性能是一个问题,在任何代码中都没有那么多值得这样做的常量。更不用说包含常量的程序集的经典版本控制问题了。
通过 C# 的 CLR 应该给我一个过度的答案,但它没有。
【问题讨论】:
-
因为它们是常量,所以发出最终将在本机转换为
mov ax, 1234h的代码最终比一直进行查找更快、更有效。立即寻址比间接寻址更快 -
“它们可能会造成严重的跨程序集版本控制问题” - 前提是您不重新编译所有内容。一般来说,在这个尽职尽责的 TDD 时代,人们无论如何都应该使用构建服务器;和 CI 服务器,而不是从你的 DEV 盒子部署,这是我能想到的唯一方法,你会遇到这样的问题。
-
"natively 最终比一直查找更快、更高效" 字节码不应该一直查找值。在我看来,可以在 jitting 到字节码而不是编译到 IL 时替换常量值。性能不会成为问题,因为每个引用程序集都需要在 jitted 时访问定义程序集一次。这就是我优雅地自相矛盾的地方:) 这种方式几乎每次出现都必须查找并替换为字节码,因为抖动通常发生在方法级别。
-
所以,是的,这里可能存在性能问题,但我仍然认为这无关紧要,因为常量值的使用远不像使用普通旧值类型那样普遍,当一个发明价值类型的主要目的是性能。