Является ли реализация синглтона с использованием авто-собственности хорошей идеей?
Недавно я узнал об авто-свойствах и их довольно много. В этот момент я пытаюсь использовать их везде, где могу. Не совсем просто использовать их везде, но больше, чтобы увидеть, насколько хорошо они работают в большинстве ситуаций.
Теперь я делаю синглтон и думал: "Эй, попробуй также авто-свойства здесь".
public class MySingleton
{
public static MySingleton MySingleton { get; private set; }
private MySingleton() {}
static MySingleton() { MySingleton = new MySingleton(); }
}
Итак, мой вопрос: "Это хорошая идея реализовать такой сингл?"
Я не спрашиваю, является ли синглтон вообще хорошей идеей.
Ответы
Ответ 1
Я лично не сделал бы этого. Мне не нравится использование автоматически реализованных свойств с помощью частного сеттера, который вы никогда не вызываете, где действительно хотите свойство только для чтения, поддерживаемое переменной только для чтения. Это еще одна строка кода, чтобы быть более явным в том, что вы имеете в виду:
public sealed class MySingleton
{
private static readonly MySingleton mySingleton;
public static MySingleton MySingleton { get { return mySingleton; } }
private MySingleton() {}
static MySingleton() { mySingleton = new MySingleton(); }
}
Таким образом, никто даже не захотел изменить класс singleton для переназначения свойства или переменной, потому что компилятор остановит их. Им нужно будет добавить сеттер и/или сделать переменную не-readonly, что является большим изменением - которое, надеюсь, они пересмотрят.
Другими словами:
- Да, это сработает.
- Нет, я не думаю, что это хорошая идея.
С С# 6 это проще с автоматически реализованными свойствами только для чтения:
public sealed class MySingleton
{
public static MySingleton MySingleton { get; } = new MySingleton();
private MySingleton() {}
static MySingleton() {}
}
Ответ 2
Я бы приблизился к этому с немного другого направления, чем Джон. Независимо от того, является ли объект одноэлементным, он логически лучше всего моделируется как свойство в первую очередь?
Свойства должны представлять... свойства. (Капитан Очевидный снова наносит удар!) Знаешь. Цвет. Длина. Высота. Имя. Родитель. Все вещи, которые вы логически считаете собственностью вещи.
Я не могу представить себе свойство объекта, логически одноэлементного. Возможно, вы придумали сценарий, о котором я не думал. Сегодня утром у меня не было диеты доктора Пеппера. Но я подозрительно, что это злоупотребление семантикой модели.
Можете ли вы описать, что такое синглтон, и почему вы считаете, что это свойство чего-то?
Все, что сказал, я сам часто использую эту схему; обычно вот так:
class ImmutableStack<T>
{
private static readonly ImmutableStack<T> emptystack = whatever;
public static ImmutableStack<T> Empty { get { return emptystack; } }
...
Является ли "пустой" логически свойство неизменяемого стека? Нет. Здесь неотразимое преимущество:
var stack = ImmutableStack<int>.Empty;
превосходит мое желание свойств, чтобы логически быть свойствами. Высказывание
var stack = ImmutableStack<int>.GetEmpty();
просто кажется странным.
Лучше ли в этом случае иметь поле readonly и регулярное свойство, или статический ctor и автопропуск, кажется менее интересным вопросом, чем вопрос о том, сделать ли это свойство в первую очередь. В "пуристском" настроении я, скорее всего, столкнулся с Джоном и сделаю его полем для чтения. Но я также часто использую шаблон создания автопрограмм с частными сеттерами для логически неизменных объектов, только из лени.
Как это для принятия всех сторон вопроса?
Ответ 3
См. это о том, как правильно реализовать синглтон.
И вы знаете, что синглтоны - это зло, верно?
Ответ 4
Я не вижу причин, почему это было бы неправильно. В конце концов, авто-свойства - это просто синтаксический сахар для аксессуаров для частного (созданного компилятором) поля поддержки.
Ответ 5
Конечно, я не вижу никаких проблем с этим.
Ответ 6
Авто property? Нет, я бы не использовал сеттер на синглете, да, да. Я думаю, вам нужно больше контроля над ним, чем даст вам свойство auto.
... конструктивная обратная связь более чем приветствуется здесь, пожалуйста. Это похоже на смелый (или глупый) шаг в этой уважаемой компании...
Мой сценарий - приложение WPF с текущим проектом, которое может быть загружено и сохранено. Текущие настройки проекта используются по всему приложению...
- в привязках WPF в пользовательском интерфейсе, чтобы пользователь мог изменить настройки, следовательно, интерфейс
INotifyPropertyChanged
.
- Я также использую Fody.PropertyChanged, но это не изменяет статические свойства, следовательно
NotifyStaticPropertyChanged
.
-
INotifyPropertyChanged
отлично работает с привязками WPF к свойствам singleton.
- Экземпляр
Settings
является [de] сериализован с использованием JSON.NET, поэтому атрибут [JsonIgnore]
на одноэлементном. Я проверяю его перед загрузкой в одноэлементный режим или сохранением его на диске.
- регистратор Serilog. Вы регистрируете материал, не так ли?
- singleton имеет
public
с public
getter, потому что привязки WPF работают только с общедоступными свойствами. Установщик internal
не влияет на него. Все свойства Settings
являются общедоступными для привязки WPF.
Я оставил весь "шум" в коде, потому что некоторые могут найти его полезным.
class Settings : INotifyPropertyChanged
{
private static Settings _currentSettings = new Settings();
/// <summary> The one and only Current Settings that is the current Project. </summary>
[JsonIgnore] // so it isn't serialized by JSON.NET
public static Settings CurrentSettings // http://csharpindepth.com/Articles/General/Singleton.aspx
{
get { return _currentSettings; }
// setter is to load new settings into the current settings (using JSON.NET). Hey, it works. Probably not thread-safe.
internal set
{
Log.Verbose("CurrentSettings was reset. Project Name: {projectName}", value.ProjectName);
_currentSettings = value;
_currentSettings.IsChanged = false;
NotifyStaticPropertyChanged("CurrentSettings");
}
}
// http://10rem.net/blog/2011/11/29/wpf-45-binding-and-change-notification-for-static-properties
/// <summary> Fires when the Curent CurrentTvCadSettings is loaded with new settings
/// Event queue for all listeners interested in StaticPropertyChanged events. </summary>
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged = delegate { };
private static void NotifyStaticPropertyChanged(string propertyName)
{
StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
}
// various instance properties including ....
public string ProjectName {get; set;}
[JsonIgnore]
public bool IsChanged { get; set; }
}
для установки singleton в недавно загруженный проект, Settings
просто
Settings settings = new Settings();
// load, save, deserialize, set properties, go nuts
Settings.CurrentSettings = settings;
Установитель, вероятно, не является потокобезопасным, но я устанавливаю его только в одном месте из потока пользовательского интерфейса, поэтому я не боюсь. Вы можете сделать его потокобезопасным после уважаемого совета http://csharpindepth.com/Articles/General/Singleton.aspx
Я понимаю, что OP не спрашивал о WPF, но я думаю, что это важно для того, чтобы показать, почему вы можете установить одноэлемент. Я сделал это, потому что это самое простое решение.