Я хотел бы сделать что-то вроде этого:
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.
}
Это позволило бы мне управлять глобальным набором Foo
s отовсюду. Однако мне сказали, что статические классы должны всегда быть не сохраняющими состояние - Вы не должны использовать их, чтобы хранить глобальные данные. Глобальные данные в целом, кажется, осуждены. Если я не должен использовать статический класс, что правильный путь состоит в том, чтобы приблизиться к этой проблеме?
Примечание: Я действительно находил подобный вопрос, но данный ответ действительно не применяется в моем случае.
Кто сказал, что статические классы должны быть без статических свойств? Статический означает заявленный.
Просто узнайте, как статические классы работают в CLR:
Также помните о проблемах параллелизма.
В качестве примечания, меня поражает, как часто люди говорят: "Не используйте X". Это похоже на то, как если бы кто-то вошел в ваш инструментарий, указал на полдюжины инструментов и сказал: "Эти инструменты - плохая практика". Это бессмысленно.
В целом это неплохо. В некоторых редких случаях это необходимо, чем реализация чего-то другого с большими накладными расходами.
Но рекомендуется следить за безопасностью потоков.
Вы должны блокировать каждый вызов вашего словаря, чтобы только один поток мог получить к нему доступ одновременно.
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;
}
}
Используйте статическое свойство только для чтения в вашем классе, это свойство будет одинаковым для всех экземпляров класса. Увеличивайте его и уменьшайте по мере необходимости из конструктора и т.д.
То, что вы, похоже, ищете здесь, это класс синглтонов, а не статический класс. Статические классы и методы следует ссылаться на процедуры без состояния. Экземпляр однопользовательского класса создается один раз и только один раз за запуск приложения и обладает полной функциональностью класса как такового. Каждый раз, когда вы ссылаетесь на него в будущем, вы будете получать обратно тот же экземпляр с точно такими же свойствами члена.
Первый результат Google для «синглтона C#», кажется, имеет довольно приличное объяснение реализации. http://www.yoda.arachsys.com/csharp/singleton.html
Я постоянно использую списки в статических классах для вещей, которые никогда не будут ( или очень редко) изменить - удобно для загрузки списков выбора и тому подобного, не нажимая каждый раз db. Поскольку я не разрешаю вносить изменения, мне не нужно беспокоиться о блокировке / контроле доступа.
Еще одна вещь, которую следует принять во внимание, - это само приложение и его бюджет. Действительно ли есть необходимость в чем-то более сложном, чем статический класс?
Глобальные данные - это одновременно мощный инструмент и частый источник проблем, поэтому используются такие методы, как внедрение зависимостей. Вы можете рассматривать это как обычную проблему развязки. Наличие глобальных данных, на которые есть прямые ссылки во многих местах вашей программы, создает прочную связь между этими глобальными данными и всеми этими местами.
Однако в вашем примере вы изолировали доступ к данным в класс, который контролирует точные детали доступа к глобальным данным. Поскольку некоторые глобальные данные часто неизбежны, я думаю, что это хороший подход.
Вы можете, например, сравнить, как app.config и web.config используются в .NET framework. Доступ к ним осуществляется через статический класс System.Configuration.ConfigurationManager со статическим свойством AppSettings , которое скрывает детали того, как получить доступ к глобальным данным.