Когда использовать статические классы в C# [дубликат]

этот вопрос уже есть ответ здесь:

  • класс с одним методом - лучший подход? 14 ответов

вот что MSDN должен сказать под когда использовать статические классы:

static class CompanyInfo
{
    public static string GetCompanyName() { return "CompanyName"; }
    public static string GetCompanyAddress() { return "CompanyAddress"; }
    //...
}

использовать статический класс как единицу организация для методов не связанные с определенными объектами. Кроме того, статический класс может сделать ваш реализация проще и быстрее потому что вам не нужно создавать объект для вызова его методов. Полезно организовать методы внутри класса значимым образом, например, методы класса Math в пространстве имен System.

Мне кажется, что этот пример не охватывает очень много возможных сценариев использования для статических классов. В прошлом я использовал статические классы для люксы связанных функций без гражданства, но это о нем. Итак, при каких обстоятельствах класс должен (и не должен) объявляться статическим?

11 ответов


Я написал свои мысли о статических классах в более раннем ответе переполнения стека: класс с одним методом-лучший подход?

Я любил служебные классы, заполненные статическими методами. Они сделали большую консолидацию вспомогательных методов, которые в противном случае лежали бы вокруг, вызывая избыточность и ад обслуживания. Они очень просты в использовании, нет экземпляра, нет утилизации, просто огонь и Форгет. Думаю, это была моя первая невольная попытка создать сервис-ориентированная архитектура - множество услуг без гражданства, которые просто выполняли свою работу и ничего больше. Однако по мере роста системы появляются драконы.

полиморфизм

скажем, у нас есть метод UtilityClass.Метода someMethod, что радостно жужжит вместе. Внезапно нам нужно немного изменить функциональность. Большинство функций одинаковы, но мы должны изменить пару частей, тем не менее. Если бы не статический метод, мы могли бы сделать производный класс и измените содержимое метода по мере необходимости. Поскольку это статический метод, мы не можем. Конечно, если нам просто нужно добавить функциональность до или после старого метода, мы можем создать новый класс и вызвать старый внутри него - но это просто грубо.

беды интерфейс

статические методы не могут быть определены через интерфейсы по логическим причинам. И поскольку мы не можем переопределить статические методы, статические классы бесполезны, когда нам нужно передать их по их взаимодействие. Это делает нас неспособными использовать статические классы как часть шаблона стратегии. Мы могли бы исправить некоторые проблемы передача делегатов вместо интерфейсов.

тестирование

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

воспитывает капли

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

параметр creep

для начала, этот маленький милый и невинный статический метод может принимать один параметр. По мере роста функциональности добавляется несколько новых параметров. Вскоре добавляются дополнительные параметры, которые являются необязательными, поэтому мы создаем перегрузки метода (или просто добавляем значения по умолчанию на языках, которые их поддерживают). Вскоре у нас есть метод, который принимает 10 параметров. Только первые три действительно необходимы, параметры 4-7 являются необязательными. Но если указан параметр 6, необходимо заполнить также 7-9... Если бы мы создали класс с единственной целью сделать то, что сделал этот статический метод, мы могли бы решить эту проблему, приняв необходимые параметры в конструкторе и разрешив пользователю устанавливать необязательные значения через свойства или методы для установки нескольких взаимозависимых значений одновременно. Кроме того, если метод вырос до такой сложности, он, скорее всего, должен быть в своем собственном классе в любом случае.

требовать от потребителей создания экземпляра классов без причины

один из наиболее распространенных аргументов: зачем требовать, чтобы потребители нашего класса создавали экземпляр для вызова этого единственного метода, не имея использования для экземпляра впоследствии? Создать экземпляр класса очень дешевая операция в большинстве языков, поэтому скорость не является проблемой. Добавление дополнительной строки кода потребителю-это низкая стоимость закладки фундамента гораздо более приемлемого решения в будущем. И, наконец, если вы хотите избежать создания экземпляров, просто создайте одноэлементную оболочку своего класса, которая позволяет легко повторно использовать - хотя это делает требование, чтобы ваш класс не имел состояния. Если он не является апатридом, вы все равно можете создавать статические методы обертки, которые обрабатывают все, предоставляя вам все преимущества в долгосрочной перспективе. Наконец, вы также можете создать класс, который скрывает экземпляр, как если бы он был одноэлементным: MyWrapper.Экземпляр-это свойство, которое просто возвращает new MyClass();

Только ситхи все возводят в абсолют

конечно, есть исключения в моей нелюбви к статическим методам. Истинные классы полезности, которые не представляют никакого риска для раздувания, являются отличными случаями для статических методов-системы.Преобразование в качестве примера. Если ваш проект является одноразовым без требований к будущему обслуживанию, общая архитектура действительно не очень важна-статическая или нестатическая, не так ли действительно, скорость развития имеет значение.

стандарты, стандарты, стандарты!

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


при принятии решения о том, делать ли класс статическим или нестатическим, вам нужно посмотреть, какую информацию вы пытаетесь представить. Это влечет за собой более 'снизу-вверх ' стиль программирования, где вы фокусируетесь на данных, которые вы представляете в первую очередь. Является ли класс, который вы пишете, реальным объектом, таким как камень или стул? Эти вещи являются физические и физические атрибуты, такие как цвет, вес, который говорит вам, что вы можете создать несколько объектов с разными свойства. Мне может понадобиться черный стул и красный стул одновременно. Если вам когда-либо понадобятся две конфигурации одновременно, вы сразу поймете, что хотите создать экземпляр как объект, чтобы каждый объект был уникальным и существовал одновременно.

с другой стороны, статические функции, как правило, предоставляют больше действий, которые не принадлежат реальному объекту или объекту, который вы можете легко представить. Помните, что предшественниками C#являются C++ и C, где вы можете просто определить глобальный функции, которые не существуют в классе. Это придает больше 'сверху вниз'. Статические методы могут использоваться для этих случаев, когда не имеет смысла, что "объект" выполняет задачу. Заставляя вас использовать классы, это упрощает группирование связанных функций, что помогает создавать более поддерживаемый код.

большинство классов могут быть представлены статическими или нестатическими, но когда вы сомневаетесь, просто вернитесь к своим корням ООП и попробуйте подумать о том, что вы представляете. Это объект, который выполняет действие (автомобиль, который может ускорить, замедлить, повернуть) или что-то более абстрактное (как отображение выходной).

свяжитесь со своим внутренним ООП, и вы никогда не ошибетесь!


для C# 3.0 методы расширения могут существовать только в статических классах верхнего уровня.


Если вы используете инструменты анализа кода (например,FxCop), он будет рекомендовать вам отметить метод static Если этот метод не имеет доступа к данным экземпляра. Причина в том, что есть прирост производительности. MSDN: CA1822-отметить участников как статические.

на самом деле это скорее руководство, чем правило...


Я предпочитаю использовать статические классы для фабрик. Например, это класс logging в одном из моих проектов:

public static class Log
{
   private static readonly ILoggerFactory _loggerFactory =
      IoC.Resolve<ILoggerFactory>();

   public static ILogger For<T>(T instance)
   {
      return For(typeof(T));
   }

   public static ILogger For(Type type)
   {
      return _loggerFactory.GetLoggerFor(type);
   }
}

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


Я начал использовать статические классы, когда я хочу использовать функции, а не классы, как мой блок повторного использования. Раньше я думал только о зле статических классов. Однако, узнав F# заставило меня увидеть их в Новом Свете.

что я имею в виду? Ну, скажем, при разработке какой-то супер сухой код, я получаю кучу классов с одним методом. Я могу просто вытащить эти методы в статический класс, а затем ввести их в зависимости с помощью делегат. Это также хорошо играет с my инъекции зависимостей (DI) контейнер выбора Autofac.

конечно, принимая прямую зависимость от статического метода по-прежнему обычно зло (есть некоторые не злой использует).


статические классы очень полезны и имеют место, например библиотек.

лучшим примером, который я могу предоставить, является .Net Math class, статический класс пространства имен System, который содержит библиотеку математических функций.

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

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

C#.Net содержит ряд статических классов, которые используются так же, как класс Math.

поэтому, учитывая правильную реализацию, они чрезвычайно полезны.

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


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

кроме этого, я думаю, что "используйте статический класс как единицу организации для методов, не связанных с конкретными объектами.- хорошо опишите их предназначение.


Это еще один старый, но очень горячий вопрос, так как ООП вмешался. Конечно, есть много причин использовать(или нет) статический класс, и большинство из них были охвачены множеством ответов.

Я просто добавлю свои 2 цента к этому, сказав, что я делаю класс статическим, когда этот класс является чем-то уникальным в системе, и это действительно не имеет смысла иметь какие-либо экземпляры этого в программе. Однако, я оставляю это использование для больших классов. Я никогда не заявляю такие небольшие классы, как в Примере MSDN, как "статические" и, конечно же, не классы, которые будут членами других классов.

Я также хотел бы отметить, что static методы и статический!--5-->классы это две разные вещи, чтобы рассмотреть. Основными недостатками, упомянутыми в принятом ответе, являются статические методы. static классы предложите такую же гибкость как нормальные классы(где свойства и параметры обеспокоены), и все методы, используемые в них, должны иметь отношение к цели существования класса.

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


Я использую только статические классы для вспомогательных методов, но с появлением в C# 3.0, я бы предпочел использовать методы расширения для них.

Я редко использую методы статических классов по тем же причинам, почему я редко использую одноэлементный "шаблон дизайна".


на основе MSDN:

  1. вы не можете создать экземпляр для статических классов
  2. если класс объявлен как статический, переменная-член должна быть статической для этого класса
  3. запечатано [не может быть унаследовано]
  4. не может содержать конструктор экземпляра
  5. Управление Памятью

пример: математические вычисления (математические значения) не изменяется [стандартный расчет для определенных значений]