c# - 为什么可以使用反射更改只读字段的值而不是 const 的值?

标签 c# reflection

为什么可以使用反射修改 readonly 字段的值而不是 const 的值?

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";
}

我读过 this answer所以我知道可以违反 readonly 的规则,但在那种情况下为什么不能违反 const 的规则?我确定有一个很好的理由,但我不知道它可能是什么。

-- 编辑--

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

我的意思是,即使 const 的值在二进制文件中是“硬编码”的,但无法修改它的原因是框架本身的技术限制,因为“它已经设置”或只是一个设计决定。我看不出有什么理由不能在某处修改 const,因为它是为 readonly 做的。

-- 编辑 2 --

要加到已接受的答案中,还有 this other answer这很有趣。在问这个问题时,我首先没有得到的是 const 背后的值 真的 在代码中使用它的任何地方都被替换了。有了这个声明:

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 值的工作方式,它们的值被复制到每个使用它们的程序集中。而 readonly 字段在运行时进行评估。

关于c# - 为什么可以使用反射更改只读字段的值而不是 const 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15458694/

相关文章:

C#如何从mysql数据库表中获取行标题

reflection - 遍历 Scheme 函数作为列表

java - 什么代表反射TypeVariable接口(interface)

c# - 在运行时修改 linq 查询

c# - db4o SODA 比较字段值

c# - 在 customMessageBox 中显示两个文本框?

c# - HttpClient 中的 PostAsync 不向我的 webapi 发送数据

go - 检查类型变量

c# - 通过反射动态创建通用列表时出错

java - 按类型和值创建 Java 枚举作为字符串