Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

reflection

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)
like image 750
Guillaume Avatar asked Mar 17 '13 07:03

Guillaume


People also ask

What is the difference between the const and the static readonly?

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.

What is the difference between constant and readonly variables in C#?

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.

How do you assign a value to a readonly variable in C#?

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.


2 Answers

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.

like image 192
ColinE Avatar answered Sep 16 '22 21:09

ColinE


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.

like image 38
PSL Avatar answered Sep 20 '22 21:09

PSL