如何在内存中分配C#const成员?

时间:2014-05-07 22:28:26

标签: c# memory-management const

问题的标题是自我解释的。我想知道声明const的成员是否是该类的所有实例的单例,或者每个实例都拥有它自己的副本。

我已经阅读了一些关于const的问题,但大多数问题都是指方法中的const变量。

6 个答案:

答案 0 :(得分:5)

C#常量实现为Common Language Instructructure中具有literal约束的字段。查找ECMA-335 §I.8.6.1.2提供了明确的答案(强调我的):

  

文字约束承诺位置的值是   实际上是内置类型的固定值。该值指定为   约束的一部分。 编译器需要更换所有   因此需要引用具有其值的位置,以及[虚拟执行系统]   不为该位置分配空间。这种约束,虽然在逻辑上   适用于任何地点,只能放在静止的地方   复合类型。不允许使用如此标记的字段   从CIL引用(它们应在内联到它们的常数值   编译时间),但可以使用反射和工具   直接处理元数据

所以你要去,const字段的值必须由编译器直接复制到指令流中(通常使用ldc.*指令)。它们不存在于可引用的位置,但需要在元数据和反射中可用。它们可以像静态字段一样实现,但不必如此。

答案 1 :(得分:2)

const隐含static,因此每个类只有一个实例。

修改:添加Reference

答案 2 :(得分:2)

常量通常可以在编译时进行评估,编译器可能会用评估值替换它。

同样Const表示static(请参阅下面的链接)

  

常量表达式是一个可以在中完全计算的表达式   编译时间。因此,常量的唯一可能值   引用类型是字符串和null。

来源:

C# static and const variables memory

Memory allocation for const in C#

C# do const fields use less memory?

答案 3 :(得分:2)

常量在编译时解析,常量的实际值存储在已编译的DLL中,而不是对常量的引用。

此外,常量将保存为DLL中类的成员。这允许外部DLL引用公共常量。但是,外部引用在编译时也会转换为常量值。

常量的编译属性的分支意味着如果DLL1引用外部DLL2中的常量,并且DLL2中的常量定义发生更改,则DLL1 将不会具有更新的值,除非它是也重新编译。

如果你想解决这个问题,你最好使用返回常量的公共属性。有关详细信息,请参阅this question的答案。

我使用.NET Reflector确认了上述行为。

答案 4 :(得分:1)

我相信价值本身在编译时被引用的任何地方都有。这意味着,如果我有const int x = 10;然后我在整个源代码中使用了x 100次,那么对x的100个引用中的每一个实际上都会被10替换为{{1}}之前的{{1}}实际编译。

答案 5 :(得分:1)

Const是元数据...
它不在内存中,而是使用const - 告诉编译器"你看到该const名称下的文字...把它放在这里" (字面值是代码中间的数字,字符串或null,如for (int i = 0... 0是文字的null

现在,在大多数情况下 - 这些(文字......从现在开始 - 我们正在谈论文字)是价值类型......单身人士与价值类型有什么关系?!没有...值类型的数据从一个位置复制到另一个位置。所以它不能是单身人士。

null怎么样? null是参考的一个可能值,它表示“我没有引用任何内容”#34; - 再说一遍.. Singleton与此无关(对于可空值的类型 - "hello world"就像默认构造函数一样......而且它们是值类型......所以这就像情况1)。

那么字符串文字怎么样?! (例如:代码中间的string ab = "ab"; string anotherAB = "ab"; string another = 'a'.ToString() + 'b'.ToString(); Console.WriteLine(object.ReferenceEquals(ab, anotherAB)); // true Console.WriteLine(object.ReferenceEquals(ab, "ab")); // true Console.WriteLine(object.ReferenceEquals(ab, another)); // false Console.WriteLine(object.ReferenceEquals("ab", another)); // false ) 这是一个特例。

每个字符串文字都缓存在一个实习表中...所以 - 每次使用相同的字符串文字时 - 你实际上是在内存中引用相同的对象。 但是,并不意味着具有相同值的每个字符串都是同一个对象:

{{1}}