Порядок инициализации статических полей в C#


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

Статические поля

Поля могут быть объявлены статическими так же, как методы и свойства. Добавление ключевого слова static указывает на то, что доступ к полю возможен с помощью добавления имени своего класса, а не через экземпляр класса. Если статическое поле является private, это значение может быть только прочитано; манипуляция им может производиться только внутри класса некоторыми типами (экземплярами) и только одно значение сохраняется и распределяется между этими экземплярами. Если к полю имеется более широкий доступ, то для всех типов, которые имеют доступ к нему, будет «видно» одно и то же значение.

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

class AControl
{
    internal static int DifVal = MaxVal - MinVal;
    internal static int MaxVal = 8;
    internal static int MinVal = 3;
}
На первый взгляд код кажется правильным. Имеем максимальное значение 8, минимальное 3 и можем ожидать, что DifVal будет равняться пяти. Однако, если вы запустите следующий код для вывода значений, то вы увидите результаты, которые не были ожидаемы:

Console.WriteLine("Maximum: {0}", AControl. MaxVal);
Console.WriteLine("Minimum: {0}", AControl. MinVal);
Console.WriteLine("Difference: {0}",AControl. DifVal);

/* OUTPUT 
Maximum:   8
Minimum:   3
Difference: 0
*/
Как вы можете видеть в комментариях, значение DifVal подсчитано неверно.

C # Спецификация

Разгадка неожиданного получения такого значения кроется в спецификации языка C#. Дело в том, что статические поля не могут рассматриваться как неинициализированные значения. Если они доступны, прежде чем им было присвоено значение, то возвращается то значение, которое используется по умолчанию для этого типа данных. Для целочисленного значения это нуль. Также спецификация языка C # говорит нам о том, что, когда статические поля инициализируются путем применения значения в их декларации, как мы делали выше, они устанавливаются в том порядке, в котором они появляются в коде. Это значит, что, когда рассчитывается DifVal, мы используем два неинициализированных значения, каждое из которых дает результат равный нулю.

Исправить это можно просто изменив порядок декларирования полей:

class AControl
{
    internal static int MaxVal = 8;
    internal static int MinVal = 3;
    internal static int DifVal = MaxVal - MinVal;
}
Теперь запуск программы дает правильные результаты:

Maximum: 8
Minimum: 3
Difference: 0

К сожалению, такой подход не создает идеального кода: читаемого и поддерживаемого. Вполне возможно, что позднее другой разработчик может изменить порядок полей, например, чтобы отсортировать их в алфавитном порядке; невольно станет причиной ошибки. Лучше исправить это, удалить из инициализации объявления поля и установить значения в пределах статического конструктора, как показано ниже:

class AControl
{
    internal static int MaxVal;
    internal static int MinVal;
    internal static int DifVal; 
    static AControl ()
    {
        MaxVal = 8;
        MinVal = 3;
        DifVal = MaxVal - MinVal;
    }
}
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, си шарп, спецификация, поля, static




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




Анализ алгоритмов: классификация
Урок 15. Параллельный LINQ
Нейронная сеть, распознающая рукописные символы, или помощь в компиляции проекта Java/C++