Why is it possible to change the value of the readonly field using reflection, but not the value of a 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"; }
I read this answer , so I understand that it is allowed to break the rules for readonly , but why not for const in this case? I am sure there is a good reason, but I cannot understand what it can be.
- Change -
When I look at the code above using ildasm, the value of the readonly field is set at compile time. Not in the field itself, unlike const , but in the constructor of the class. Therefore, I am not sure why you can “overwrite” and not another.
What I mean, even if the const value is “hard-coded” in binary, is the reason that it cannot modify it as a technical limitation in the structure itself, because “it is already installed”, or just a design decision. I see no reason why there cannot be some kind of “magic”, somewhere const modifications, as is done for readonly .
- Change 2 -
To add to the accepted answer, there is this other answer , which is quite interesting. What I did not get in the first place, asking this question, is that the value of const indeed replaced at any place that it is used in the code. With this ad:
public const string Foo = "Hello";
writing later
Console.WriteLine(Foo);
equivalent to writing
Console.WriteLine("Hello");
Indeed my code
Console.WriteLine(foobar.foo); Console.WriteLine(Foobar.bar);
is replaced in IL by
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)