为什么“ someValue”变量是只读的(但我们仍然可以通过反射更改其值),但实际上却更改为55,却输出为“ 10”?
static class Program
{
static readonly int someValue = 10;
static void Main(string[] args)
{
Console.WriteLine(someValue); // 10
typeof(Program)
.GetField("someValue", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, 55); // change readonly field via reflection to 55
Console.WriteLine(someValue); // output in console 10,
// but in visual studio debugger it shows 55
Console.ReadKey();
}
}
答案 0 :(得分:2)
可能只是JIT优化,以防止多次读取变量。
您正在更改已声明为只读的内存位置,因此,如果读者缓存这些值,请不要感到惊讶。
答案 1 :(得分:0)
这是JIT编译器的优化。 JIT内联静态只读字段。
让我解释一下。
让我们从简单的事实开始:
静态构造函数在每种类型的过程中仅被调用一次。
因此,静态只读字段只能初始化一次,这与实例只读字段不同: 实例构造函数可以被多次调用(以创建一个类的新实例),因此在实例只读字段中可以有多个不同的值。您不能在方法中内联某个实例的readonly字段,因为该方法可能正在使用其他实例。
当您访问任何类型或其实例的数据或函数或其他内容时,该类型的静态构造函数已被调用。
这意味着,访问类型时,始终首先调用静态构造函数。因此,静态只读字段必须已经初始化!
JIT编译器完全了解我在上面所说的内容。
那么,为什么不决定在使用它的方法中内联该静态只读字段呢?
请参见,如果某个方法正在使用该静态只读字段,则它正在访问该类型。如果正在访问该类型,则该类型的静态构造函数已经被调用,并且静态只读字段已经被初始化。静态构造函数将永远不会再被调用,并且静态只读字段将具有相同的值,直到您不重新启动应用程序为止!如果我们知道该字段将始终具有相同的值,为什么不将其内联到方法中呢?