Singleton.cs
Код подключён напрямую из исходного файла в кодировке UTF-8, поэтому эта страница всегда показывает его актуальную версию.
← К конспекту
Скачать исходный файл
| Singleton.cs |
|---|
| using System;
using System.Threading;
namespace DesignPatterns.Creational.Singleton
{
/// <summary>
/// Классический потокобезопасный Singleton на основе Lazy<T>.
/// Lazy<T> сам по себе уже реализует ленивую и потокобезопасную инициализацию,
/// поэтому вручную писать double-checked locking в 99% случаев не требуется.
/// </summary>
public sealed class AppSettings
{
private static readonly Lazy<AppSettings> LazyInstance =
new(() => new AppSettings(), LazyThreadSafetyMode.ExecutionAndPublication);
public static AppSettings Instance => LazyInstance.Value;
public string ConnectionString { get; }
// Приватный конструктор - никто, кроме самого класса, не может создать экземпляр через new.
private AppSettings()
{
// Здесь могла бы быть тяжёлая инициализация: чтение файла конфигурации,
// разбор переменных окружения и т.д. Она выполнится один раз, при первом обращении.
ConnectionString = "Host=localhost;Database=demo";
}
}
/// <summary>
/// То же самое, но через статический конструктор - альтернативный вариант,
/// который CLR гарантированно выполняет один раз и потокобезопасно ещё до первого
/// обращения к любому статическому члену типа.
/// </summary>
public sealed class FeatureFlags
{
// Статический конструктор выполняется лениво (при первом обращении к типу)
// и потокобезопасно - это гарантирует сам CLR.
private static readonly FeatureFlags InstanceField = new();
public static FeatureFlags Instance => InstanceField;
public bool NewCheckoutEnabled { get; }
private FeatureFlags()
{
NewCheckoutEnabled = true;
}
}
public static class Demo
{
public static void Run()
{
var s1 = AppSettings.Instance;
var s2 = AppSettings.Instance;
Console.WriteLine(ReferenceEquals(s1, s2)); // True - это один и тот же объект
Console.WriteLine(s1.ConnectionString);
Console.WriteLine(FeatureFlags.Instance.NewCheckoutEnabled);
}
}
}
|