【发布时间】:2013-03-17 07:57:46
【问题描述】:
为什么可以使用反射修改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)
【问题讨论】:
-
@CodyGray 感谢您的链接。我不知道为
const处理内存的方式以及它可能对其他程序集产生的影响。修改const的值可能会对我猜的其他程序集产生未知的影响。
标签: c# reflection