Как стать автором
Обновить

Комментарии 16

Итак: статический конструктор вызывается перед доступом к любому члену класса, за исключением констант.

Это происходит потому что компилятор «инлайнит» значения констант. У Рихтера можно почитать про разницу статических полей и констант.
Да, очевидную для себя вещь не указал. Спасибо, подправлю.
Т.е. если я использовал константу из связанной сборки, а потом подменил эту сборку на сборку с другим значением константы, то до перекомпиляции моя сборка будет использовать старую константу?
По памяти:
Вы можете даже вообще эту сборку выкинуть из папки(только в том случае, когда из сборки используется только эта константа) — сборка даже не будет подгружаться. Соответственно, после компиляции можете подменять эту сборку сколько захотите и как захотите.
Спасибо!
Да, будет использовать старую, если нужна функциональность поддержки «меняющейся» константы из сборки, лучше использовать readonly вместо константы. Константа поэтому и называется так — она не должна меняться, например число Пи.
Век живи, век учись.Спасибо!
Утверждение о том, что статические классы и члены классов не поддерживают полиморфизм в целом, не совсем корректно. C# разрешает ad hoc и параметрический полиморфизм для «статики».
Но это при условии что статика знает о возможных параметрах.
Хотел бы привести ещё пример нежелательного использования статиков.
Временами встречаю, когда используется статический класс, который меняет своё поведение в зависимости от его свойств. Например, что то вроде этого:
MapBuilder.BuildMode = BuildMode.Default;
MapBuilder.Build();

Причём свойство BuildMode может устанавливаться в одной части программы, а вызов метода Build в другой.
Лучше использовать экземпляр объекта и использовать readonly поле для его хранения. Таким образом, зависимости в проекте будут лучше прослеживаться.
Как-то раз столкнулся с библиотекой на питоне, которая так себя вела. Каково же было моё возмущение, когда я попытался поработать с ней из нескольких потоков и обнаружил что она внутри зачем-то устанавливает своим классам статические свойства.
На мой взгляд, тут не в статике проблема.
Точно так же можно и экземпляр использовать

var mb = new MapBuilder();
mb.BuildMode = BuildMode.Default;
DoAnythingWithMapBuilder(mb); // внутри этого метода может еще раз вызваться Build() или измениться свойство BuildMode
mb.Build();

:)

А решит проблему пресловутая параметризация

MapBuilder.Build(BuildMode.Default);
Поставьте в самое начало главный вопрос когда и зачем использовать статику. А так это сухая справочная информация, а не лекция.
Например в c# нет глобальных переменных, но по необходимости можно создать статический класс GlobVars
Если попробовать выполнить приведённый ниже код, то можно убедиться в верности следующего утверждения: статический конструктор вызывается перед доступом к любому члену класса.

Вы забыли наверное упомянуть, что любой член класса должен быть обязательно НЕ статическим полем с инициализацией, иначе он вызовется перед статическим конструктором. Из спецификации шарпа:
10.5.5.1 Static field initialization The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (§10.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class

Как-то раз сам нарвался на такое поведение и долго не мог понять почему. Благодаря такому поведению можно паттерн Singleton реализовать гораздо проще нежели раньше, так как, если я правильно помню, такого поведения вроде как еще не было при .net 1.1.
Там ещё и от порядка объявления зависит инициализация статических переменных.
Надо упомянуть о том, что если статический конструктор, выбросит исключение, то это и все последующие обращения ко всем членам этого класса кроме констант, будут выбрасывать TypeInitializationException. По этой причине я придерживаюсь мнения, что статический конструктор, это всегда плохо.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории