Why is it possible to change the value of the readonly field, but not const, using reflection?

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) 
+8
reflection c #
source share
2 answers

Because the const fields are "set" at compile time, i.e. the compiler replaces the const value with the given value at compile time. As a result of using const values, their values ​​are copied to each assembly that uses them. While readonly fields are evaluated at runtime.

+9
source share

The reason is that constants are replaced with a value during compilation time itself. But the readonly fields are not. You can set the value for read-only fields in either declaraiotn or in this class constructor. Hope this answers your question.

+2
source share

All Articles