如何阻止C#用它们的值替换const变量?

我们有一个编译成名为consts.dll的DLL的项目,它包含如下内容:

public static class Consts
{
    public const string a = "a";
    public const string b = "b";
    public const string c = "c";
}

我们有这种类型的多个项目,每个都编译成一个同名的DLL(consts.dll),我们根据需要替换它们。 我们有另一个使用这些const的类:

public class ConstsUser 
{
    string f() { return Consts.a; }
}

不幸的是, Consts.a被优化为“a”,所以即使我们替换Consts.dll实现,我们仍然得到“a”而不是正确的值,我们需要重新编译ConstsUser 。 无论如何阻止优化器用它们的值替换const变量?


我认为static readonly修饰符的使用符合您的需求:

public static class Consts
{
    public static readonly string a = "a";
    public static readonly string b = "b";
    public static readonly string c = "c";
}

常量在调用站点上是硬编码的,所以这是你的问题。 静态只读变量只能在Consts类的变量声明或静态构造函数中Consts ,并且不会在呼叫站点上内联。


从本书CLR通过c#

当代码引用常量符号时,编译器在定义常量的程序集的元数据中查找符号,提取常量的值,并将该值嵌入发出的中间语言(IL)代码中 。 因为常量的值直接嵌入代码中,所以常量在运行时不需要为它们分配任何内存 。 另外,你不能得到一个常量的地址,你不能通过引用传递一个常量。 这些约束也意味着常量没有一个好的交叉汇编版本控制的故事,所以只有当您知道符号的值永远不会改变时才应该使用它们

正如我们所看到的,当我们知道符号的值永远不会改变时,使用const确实有它的好处。 它可以执行得更快,因为CLR不需要解析值。

实际上,在构建应用程序程序集之后,DLL程序集甚至不会在运行时加载,并且可以从磁盘中删除,因为编译器甚至不会在应用程序的元数据中添加对DLL程序集的引用。

正如@Sergey Berezovskiy所建议的那样,如果需要CLR 在运行时动态解析该值,我们可以使用static readonly 。 性能受此解决方案的影响,但也有另一个好处。

另外,一个字段可以是任何数据类型 ,因此您不必将自己限制在编译器的内置基本类型中(就像您对常量所做的那样)。

链接地址: http://www.djcxy.com/p/21223.html

上一篇: How to stop C# from replacing const variable with their values?

下一篇: Why does C# have 'readonly' and 'const'?