Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I change a private readonly field in C# using reflection?

People also ask

Can readonly variable be changed?

The readonly keyword can be used to define a variable or an object as readable only. 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.

What does private readonly do?

If it's private and readonly , the benefit is that you can't inadvertently change it from another part of that class after it is initialized. The readonly modifier ensures the field can only be given a value during its initialization or in its class constructor.

What are the properties of read only?

Read only means that we can access the value of a property but we can't assign a value to it. When a property does not have a set accessor then it is a read only property. For example in the person class we have a Gender property that has only a get accessor and doesn't have a set accessor.

Can a property be readonly C#?

C# ReadOnly Property FeaturesIn c#, we can create the Read-only fields using readonly keyword. In c#, you can initialize the readonly fields either at the declaration or in a constructor. The readonly field values will evaluate during the run time in c#.


You can:

typeof(Foo)
   .GetField("bar",BindingFlags.Instance|BindingFlags.NonPublic)
   .SetValue(foo,567);

The obvious thing is to try it:

using System;
using System.Reflection;

public class Test
{
    private readonly string foo = "Foo";

    public static void Main()
    {
        Test test = new Test();
        FieldInfo field = typeof(Test).GetField
            ("foo", BindingFlags.Instance | BindingFlags.NonPublic);
        field.SetValue(test, "Hello");
        Console.WriteLine(test.foo);
    }        
}

This works fine. (Java has different rules, interestingly - you have to explicitly set the Field to be accessible, and it will only work for instance fields anyway.)


I agree with the other answers in that it works generally and especially with the comment by E. Lippert that this is not documented behavior and therefore not future-proof code.

However, we also noticed another issue. If you're running your code in an environment with restricted permissions you might get an exception.

We've just had a case where our code worked fine on our machines, but we received a VerificationException when the code ran in a restricted environment. The culprit was a reflection call to the setter of a readonly field. It worked when we removed the readonly restriction of that field.


You asked why you would want to break the encapsulation like that.

I use an entity helper class to hydrate entities. This uses reflection to get all the properties of a new empty entity, and matches the property/field name to the column in the resultset, and set's it using propertyinfo.setvalue().

I don't want anyone else to be able to change the value, but I don't want to take all the effort to custom code hydration methods for every entity either.

My many of my stored procs return resultsets that don't correspond directly to tables or views, so the code gen ORM's do nothing for me.