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)
The first, const, is initialized during compile-time and the latter, readonly, initialized is by the latest run-time. The second difference is that readonly can only be initialized at the class-level. Another important difference is that const variables can be referenced through "ClassName.
ReadOnly Vs Const KeywordReadOnly is a runtime constant. Const is a compile time constant. The value of readonly field can be changed. The value of the const field can not be changed.
Use the readonly keyword in C# This means that the variable or object can be assigned a value at the class scope or in a constructor only. You cannot change the value or reassign a value to a readonly variable or object in any other method except the constructor.
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.
Reason is that the constants are replaced with it value during the compile time itself. But readonly fields are not. You can set a value for a readonly fields either at declaraiotn and/or at that class's constructor. I Hope this answers your question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With