Почему для реализации singleton в С# 6.0 не нужен флаг beforefieldinit?
Я пытаюсь понять, почему это правильная реализация шаблона Singleton:
public sealed class Singleton : ISingleton
{
public static Singleton Instance { get; } = new Singleton();
private Singleton() { }
// methods
}
Как насчет флага beforefieldinit
? Согласно Jon Skeet article:
Лень инициализаторов типов гарантируется только .NET, когда тип не помечен специальным флагом, называемым beforefieldinit. К сожалению, компилятор С# (как указано в среде выполнения .NET 1.1) помечает все типы, у которых нет статического конструктора (т.е. Блок, который выглядит как конструктор, но помечен как статический), как beforefieldinit.
Не нужен ли статический конструктор в новейшей версии С#?
Код выше - это реализация SystemClock
в проекте NodaTime, Джон Скит. '
ИЗМЕНИТЬ
Код Jon Skeet для справки (почему я упоминаю этот флаг beforefieldinit):
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
Ответы
Ответ 1
Оба являются правильными одноэлементными реализациями. Нужен ли вам статический конструктор, зависит только от того, насколько вы заботитесь о полной лености. Если вы действительно, действительно не хотите, чтобы синглтон был создан до тех пор, пока он не будет использован вызывающим, у вас должен быть статический конструктор - или используйте Lazy<T>
. Вы также можете использовать статический конструктор в коде С# 6, конечно:
public sealed class Singleton : ISingleton
{
public static Singleton Instance { get; } = new Singleton();
static Singleton() { }
private Singleton() { }
// methods
}