Почему после изменения статического поля только для чтения с помощью отражения выход этого поля только для чтения устарел? - PullRequest
0 голосов
/ 26 января 2019

Почему переменная someValue, которая доступна только для чтения (но мы все еще можем изменить ее значение с помощью отражения), выводится как "10", хотя на самом деле она изменилась на 55?

static class Program
{
    static readonly int someValue = 10;

    static void Main(string[] args)
    {
        Console.WriteLine(someValue); // 10

        typeof(Program)
             .GetField("someValue", BindingFlags.Static | BindingFlags.NonPublic)
             .SetValue(null, 55); // change readonly field via reflection to 55

        Console.WriteLine(someValue); // output in console 10, 
                                      // but in visual studio debugger it shows 55

        Console.ReadKey();
    }
}

Ответы [ 2 ]

0 голосов
/ 07 мая 2019

Это оптимизация JIT-компилятора.JIT вставляет статические поля только для чтения.

Позвольте мне объяснить это.

Давайте начнем с простых фактов:

Статические конструкторы вызываются только один раз в процессе для каждого типа.

Таким образом, статическое поле только для чтения может быть инициализировано только один раз, в отличие от полей только для чтения экземпляра: конструктор экземпляра может вызываться несколько раз (для создания новых экземпляров класса), поэтому их может быть несколькоразличные значения, когда дело доходит до полей только для чтения.Вы не можете встроить поле только для чтения экземпляра в методе, потому что могут быть другие экземпляры, с которыми работает метод.

Когда вы обращаетесь к данным или функциям любого типа или его экземпляра или к чему-либо еще,Статический конструктор этого типа уже был вызван.

Это означает, что статические конструкторы всегда вызываются первыми при доступе к типу.Итак, статическое поле только для чтения должно быть уже инициализировано!

JIT-компилятор прекрасно знает, о чем я говорю выше.

Итак, почему бы не решить, чтостатическое поле только для чтения в методе, который его использует?

Смотрите, если метод использует это статическое поле только для чтения, то он обращается к этому типу.Если он обращается к этому типу, то статический конструктор этого типа уже был вызван, а статическое поле только для чтения уже инициализировано.Статический конструктор никогда не будет вызываться снова, и поле static readonly будет иметь то же значение, пока вы не перезапустите приложение!Почему бы не встроить его в метод, если мы знаем, что поле всегда будет иметь одинаковое значение?

0 голосов
/ 26 января 2019

Вероятно, просто оптимизация JIT, чтобы предотвратить чтение переменной несколько раз.

Вы изменяете область памяти, которую вы объявили как предназначенную только для чтения, поэтому не стоит удивляться, если читатели кешируют значения.

...