Skip to content

Instantly share code, notes, and snippets.

@terrajobst
Last active April 16, 2019 02:22
Show Gist options
  • Save terrajobst/0c0d623f92f7bc18933ee584259915a8 to your computer and use it in GitHub Desktop.
Save terrajobst/0c0d623f92f7bc18933ee584259915a8 to your computer and use it in GitHub Desktop.
Setting read-only fields isn't reliable

Setting read-only fields isn't reliable

Analysis by @stephentoub


You can easily see that by running this code on .NET Framework today:

using System;
using System.Reflection;

class Program
{
    private static readonly int s_readonlyValue;

    private static int s_value;

    private static void Main()
    {
        Console.WriteLine(nameof(s_value) + ":");
        for (int i = 0; i < 10; i++)
        {
            typeof(Program).GetField(nameof(s_value), BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, s_value + 1);
            Console.WriteLine(s_value);
        }

        Console.WriteLine();
        Console.WriteLine(nameof(s_readonlyValue) + ":");
        for (int i = 0; i < 10; i++)
        {
            typeof(Program).GetField(nameof(s_readonlyValue), BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, s_readonlyValue + 1);
            Console.WriteLine(s_readonlyValue);
        }
    }
}

This prints:

s_value:
1
2
3
4
5
6
7
8
9
10

s_readonlyValue:
0
0
0
0
0
0
0
0
0
0

because the JIT bakes the value of s_readonlyValue into the call site when it compiles it, and thus isn’t affected by subsequent changes to the field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment