Правильное Использование Ключевого Слова static в C#
Основная проблема в том, что static плохо сочетается с изменяемым состоянием, т.е. состоянием, которое может изменяться в течение жизненного цикла программы. Как следствие правила использования следующие:
1. Статические поля должны быть только для чтения (по возможности, константами).
2. Статические поля должны ссылаться на неизменяемое состояние.
3. Статические методы должны быть чистыми функциями, то есть вычислять результат из входных параметров, без изменения состояния входных данных или любого другого состояния.
4. Статические классы допустимы, если их поля и методы соответствуют этим рекомендациям.
Основная мотивация для создания статического поля - создать объект, который живет в течение всего времени выполнения программы. Часто это важный объект, например контекст, доступ к которому осуществляется многими методами. На первый взгляд, сделать его статическим и видимым всем удобнее, чем передавать везде как параметр. Посмотрим, какие проблемы это сулит.
1. Код должен выполняться в пределах сессии
Объект, живущий всё время, пока исполняется программа, зачастую не нужен. На самом деле состояние требуется в пределах «сессии»: в течение веб-запроса или во время выполнения тестов. При этом совместное использование изменяемого состояния – не лучшая идея. Все «сессии» теперь должны заботиться о том, чтобы общее состояние было правильно инициализировано и правильно финализировано. Кроме того, веб-запросы де-факто выполняются конкурентно. Даже тесты можно запустить параллельно. В такой ситуации вам необходимо синхронизировать доступ к статическому изменяемому состоянию. А синхронизация доступа - это не только боль, но и убийца производительности.
2. Управление состоянием в конкурентной среде
В этом случае использование одного ресурса на поток устраняет необходимость в синхронизации. Идея в том, что к объекту всегда обращается один и тот же поток, т.е. каждый поток имеет свой собственный экземпляр. Вы можете использовать для этого статическое поле, помеченное атрибутом
ThreadStatic. Конкурентный доступ при этом исключается, но каждый поток по-прежнему должен беспокоиться об управлении состоянием. Поэтому создание выделенного объекта на поток более элегантно, чем статическое поле с атрибутом ThreadStatic: так вы можете правильно отслеживать историю изменений состояния.3. Глобальное состояние и поддержка
Статические поля представляют глобальное состояние, доступ к которому можно получить из любого места кода. И разработчики могут создать зависимость от глобального состояния где угодно. Со временем это неизбежно приведёт к неуправляемому доступу к глобальному состоянию, и результатом будет подверженный ошибкам код, неконтролируемые побочные эффекты и утомительные сеансы отладки.
4. Чистые функции
Часто классы содержат функции, которые вычисляют результат без использования полей экземпляра объекта. Эти функции могут быть объявлены статическими. В результате получаются жирные классы, которые трудно понять и поддерживать. Поэтому в случае сложной логики лучше размещать такую реализацию во вспомогательных статических классах. Это не только делает классы экземпляров меньше и понятнее, но и сами статические классы хорошо поддаются тестированию: тесту нужно инициализировать входные данные, вызвать статический метод и проверить результат. Нет никакого скрытого состояния, о котором стоит беспокоиться, не нужно создавать объекты-имитации.
А методы расширения помогают не только отделить объект от его поведения, но и сделать вызовы более естественными.
Select, Where, First и т.п. - это статические методы расширения для IEnumerable, которые не изменяют входную последовательность, а возвращают новую.Итого
Ключевое слово static плохо сочетается с изменяемым состоянием. Неправильное использование обязательно приведёт к серьёзным неприятностям. Но оно может стать серьёзным подспорьем, если использовать его с умом.
Источник: https://blog.ndepend.com/the-proper-usages-of-the-keyword-static-in-c/