How to: Set read-only fields outside constructors in C#

It's a well know rule that the readonly fields can only be set in the static constructors or auto constructors. But if we just have a requirement to set it outside the constructors, can this really be done?

The answer is yes, we can crack it by using Reflection. Actually, we can get the FieldInfo which is a wrapper class which contains all the information related to a field, and  it exposes SetValue interface to us which we can leverage. 

Suppose we have the following Person type:

public class Person
{
    private int age;
    private string sex;
    readonly private static string name;
    readonly private string job;
    static Person()
    {
        name = "initial name";
    }
    public Person()
    {
        age = 10;
        sex = "male";
        job = "none";
    }
    public int Age
    {
        get
        {
            return age;
        }
    }
    public string Job
    {
        get
        {
            return job;
        }
    }
    public static string Name
    {
        get
        {
            return name;
        }
    }
    public string Sex
    {
        get
        {
            return sex;
        }
    }
}

We can see that there's a static constructor and an auto constructor giving initial values for the fields, now in a consumption code, we may write the following code:

public void Main()
{
    Person p = new Person();
    Console.WriteLine(p.Job);
    Console.WriteLine(Person.Name);
    Console.WriteLine(p.Age);

    Type type = p.GetType();
    FieldInfo nameField = type.GetField("name", BindingFlags.NonPublic | BindingFlags.Static);
    nameField.SetValue(null, "NewName");
    FieldInfo jobField = type.GetField("job", BindingFlags.NonPublic | BindingFlags.Instance);
    jobField.SetValue(p, "New Job");
    FieldInfo ageField = type.GetField("age", BindingFlags.NonPublic | BindingFlags.Instance);
    ageField.SetValue(p, 20);
    Console.WriteLine(p.Job);
    Console.WriteLine(Person.Name);
    Console.WriteLine(p.Age);
}

With this, we can also see that the trick used above can also be applied in cracking the private field.

Sometimes, when we are using components by others, we may have less control with it. So knowing this trick will help you in handling certain type of cases.

By the way, if we don't know the declaration of the fields or methods, we can get it through Object Browser of Visual Studio.


Similar Articles