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

Shm*_*opy 61 c# optimization

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

public static class Consts
{
    public const string a = "a";
    public const string b = "b";
    public const string c = "c";
}
Run Code Online (Sandbox Code Playgroud)

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

public class ConstsUser 
{
    string f() { return Consts.a; }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,Consts.a优化为"a",所以即使我们替换Consts.dll实现,我们仍然得到"a"而不是正确的值,我们需要重新编译ConstsUser.反正有没有阻止优化器用它们的值替换const变量?

Ser*_*kiy 118

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

public static class Consts
{
    public static readonly string a = "a";
    public static readonly string b = "b";
    public static readonly string c = "c";
}
Run Code Online (Sandbox Code Playgroud)

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

  • 可选参数也是如此. (2认同)

Kha*_* TO 36

从书籍CLR到c#

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

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

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

正如@Sergey Berezovskiy已经建议的那样,static readonly如果你需要CLR 在运行时动态地解析值,我们就可以使用它.此解决方案会影响性能,但还有另一个好处.

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