Why is it possible to change the value of a readonly field but not of a const using reflection?
c#, reflection
Solution
Because `const` fields are 'set' at compile time, i.e. the compiler replaces the `const` with the given value during compilation. As a result of the way `const` values work, their values are copied into every assembly that uses them. Whereas `readonly` fields are evaluated at runtime.
Problem
Why is it possible to modify the value of a `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've read this answer so I understand it's allowed to break the rules for `readonly` but why not for `const` in that case? I'm sure there's a good reason but I can't figure out what it could be. -- Edit -- When I take a look at the code above using ildasm, the value of the `readonly` field is set at compile time. Not on the field itself unlike for the `const` but in the constructor of the class. So I'm not sure to get why one can be "overwritten" but not the other one. What I mean is, even if the value of the `const` is "hard-coded" in the binary, is the reason for not being able to modifiy it a technical limitation in the framework itself because "it's already set" or just a design decision. I don't see any reason why there could not be some "magic" somewhere modifying the `const` as it's doing it for the `readonly`. -- Edit 2 -- To add up to the accepted answer, there is also this other answer which is quite interesting. What I didn't get in the first place when asking this question is that the value behind the `const` is really replaced anywhere it is used in the code. With this declaration: ``` public const string Foo = "Hello"; ``` writing later ``` Console.WriteLine(Foo); ``` is 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) ```