Это - плохая практика, чтобы иметь состояние в статическом классе?

Я хотел бы сделать что-то вроде этого:

public class Foo {
    // Probably really a Guid, but I'm using a string here for simplicity's sake.
    string Id { get; set; }

    int Data { get; set; }

    public Foo (int data) {
        ...
    }

    ...
}

public static class FooManager {
    Dictionary foos = new Dictionary ();

    public static Foo Get (string id) {
        return foos [id];
    }

    public static Foo Add (int data) {
        Foo foo = new Foo (data);
        foos.Add (foo.Id, foo);

        return foo;
    }

    public static bool Remove (string id) {
        return foos.Remove (id);
    }

    ...

    // Other members, perhaps events for when Foos are added or removed, etc.
}

Это позволило бы мне управлять глобальным набором Foos отовсюду. Однако мне сказали, что статические классы должны всегда быть не сохраняющими состояние - Вы не должны использовать их, чтобы хранить глобальные данные. Глобальные данные в целом, кажется, осуждены. Если я не должен использовать статический класс, что правильный путь состоит в том, чтобы приблизиться к этой проблеме?

Примечание: Я действительно находил подобный вопрос, но данный ответ действительно не применяется в моем случае.

11
задан Community 23 May 2017 в 10:28
поделиться

7 ответов

Кто сказал, что статические классы должны быть без статических свойств? Статический означает заявленный.

Просто узнайте, как статические классы работают в CLR:

  • Вы не можете контролировать время вызова статических конструкторов.
  • Статические классы имеют отдельное состояние для каждой вызывающей программы.

Также помните о проблемах параллелизма.

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

10
ответ дан 3 December 2019 в 06:20
поделиться

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

Но рекомендуется следить за безопасностью потоков.

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


private static readonly object LockStaticFields = new object();

public static Foo Add (int data) {
        lock(LockStaticFields)
        {
           Foo foo = new Foo (data);
           foos.Add (foo.Id, foo);

           return foo;
        }
    }

2
ответ дан 3 December 2019 в 06:20
поделиться

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

0
ответ дан 3 December 2019 в 06:20
поделиться

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

Первый результат Google для «синглтона C#», кажется, имеет довольно приличное объяснение реализации. http://www.yoda.arachsys.com/csharp/singleton.html

3
ответ дан 3 December 2019 в 06:20
поделиться

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

0
ответ дан 3 December 2019 в 06:20
поделиться

Еще одна вещь, которую следует принять во внимание, - это само приложение и его бюджет. Действительно ли есть необходимость в чем-то более сложном, чем статический класс?

0
ответ дан 3 December 2019 в 06:20
поделиться

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

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

Вы можете, например, сравнить, как app.config и web.config используются в .NET framework. Доступ к ним осуществляется через статический класс System.Configuration.ConfigurationManager со статическим свойством AppSettings , которое скрывает детали того, как получить доступ к глобальным данным.

4
ответ дан 3 December 2019 в 06:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: