重新编译引用的程序集时不变的常量值

No *_*ame 12 .net c# const c#-4.0

我在程序集中有这个代码:

public class Class1
{
    public const int x = 10;
}
Run Code Online (Sandbox Code Playgroud)

在我有一个不同的集会:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Class1.x);
        Console.ReadKey();
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,产量10,但后来我改x20:

public class Class1
{
    public const int x = 20;
}
Run Code Online (Sandbox Code Playgroud)

我重新编译了程序集并将其移动到我的命令行程序的bin目录中.但是,我的程序输出仍然是10,直到我编译包含该main函数的程序集.

为什么会这样?

Ser*_*kiy 20

C#中的常量值在使用它们的位置内嵌.即行将Console.WriteLine(Class1.x);编译为Console.WriteLine(10);.生成的IL代码如下所示:

  .entrypoint
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldc.i4.s   10  // here just integer value 10 is loaded on stack
  IL_0003:  call       void [mscorlib]System.Console::WriteLine(int32)
Run Code Online (Sandbox Code Playgroud)

没有任何与Class1的链接.因此,在重新编译Main程序集之前,它将具有内联值10.MSDN警告这种常量使用情况:

不要创建常量来表示您希望随时更改的信息.例如,不要使用常量字段来存储服务价格,产品版本号或公司的品牌名称.这些值可能会随着时间的推移而发生变化,并且由于编译器会传播常量,因此必须重新编译使用库编译的其他代码以查看更改.

他们提到仅在编译时评估常量表达式.即Class1.x将在被评估Main组件编译时间值10.如果没有重新编译,那么价值就不会改变.但不幸的是,它并没有清楚地解释这种行为的原因(至少对我而言).

BTW Named和Optional参数值也在调用方法的位置进行内联,您还需要重新编译调用程序集以更新值.