C# 为什么可以使用反射更改只读字段的值而不更改常量的值?

C# 为什么可以使用反射更改只读字段的值而不更改常量的值?,c#,reflection,C#,Reflection,为什么可以使用反射修改只读字段的值,但不能修改常量的值 class Program { static void Main(string[] args) { Foobar foobar = new Foobar(); Console.WriteLine(foobar.foo); // Outputs "Hello" Console.WriteLine(Foobar.bar);

为什么可以使用反射修改
只读
字段的值,但不能修改
常量的值

class Program
{
    static void Main(string[] args)
    {
        Foobar foobar = new Foobar();
        Console.WriteLine(foobar.foo);                   // Outputs "Hello"
        Console.WriteLine(Foobar.bar);                   // Outputs "Hello"

        var field = foobar.GetType().GetField("foo");
        field.SetValue(foobar, "World");                // Ok
        field = foobar.GetType().GetField("bar");
        field.SetValue(foobar, "World");                // Throws FieldAccessException

        Console.ReadKey();
    }
}

public class Foobar
{
    public readonly string foo = "Hello";
    public const string bar = "Hello";
}
我已经读过了,所以我知道可以违反
只读
的规则,但在这种情况下为什么不违反
常量
?我相信这有一个很好的理由,但我不知道这可能是什么

--编辑--


当我使用ildasm查看上面的代码时,
readonly
字段的值是在编译时设置的。与
常量不同,不是在字段本身上,而是在类的构造函数中。所以我不确定为什么一个可以被“覆盖”,而另一个不能

我的意思是,即使
const
的值是二进制的“硬编码”,也不能修改它的原因是框架本身的一个技术限制,因为“它已经设置好了”或者只是一个设计决策。我看不出有什么理由不能在某个地方修改
常量,因为它是为
只读
而做的

--编辑2--

加上公认的答案,还有一个非常有趣的问题。当我问这个问题时,我首先没有得到的是
常量后面的值实际上在代码中使用的任何地方都会被替换。根据本声明:

public const string Foo = "Hello";
稍后再写

Console.WriteLine(Foo);
相当于写作

Console.WriteLine("Hello");
确实是我的代码

Console.WriteLine(foobar.foo);
Console.WriteLine(Foobar.bar);
在IL中被替换为

IL_0008:  ldfld      string ConsoleApplication3.Foobar::foo
IL_000d:  call       void [mscorlib]System.Console::WriteLine(string)
IL_0012:  nop
IL_0013:  ldstr      "Hello"
IL_0018:  call       void [mscorlib]System.Console::WriteLine(string)

因为
const
字段是在编译时“设置”的,即编译器在编译期间用给定值替换
const
。由于
const
值的工作方式,它们的值被复制到使用它们的每个程序集中。然而,
只读
字段是在运行时计算的。

原因是在编译时本身,常量被替换为it值。但只读字段不是。您可以在DeclarationN和/或该类的构造函数中为只读字段设置值。我希望这能回答您的问题。

当我在ildasm中查看问题中的代码时,
readonly
字段的值也在编译时设置。与
常量不同,不是在字段本身上,而是在构造函数中。因此,我仍然不确定为什么一个可以被“覆盖”,而另一个不能被“覆盖”。@Guillaume您可以更新您的问题,将您对常量和只读的IL观察包括在内。@Guillaume您可能观察到的是编译器优化,在这种情况下,您的只读显示与常量声明相同。你不能从编译的代码中推断太多!另请参阅:@CodyGray感谢您的链接。我不知道
const
的内存处理方式以及它对其他程序集的影响。修改
const
的值可能会对其他程序集产生未知的影响。