Singleton на C#: когда применять и как реализовать
Паттерн Singleton (одиночка) гарантирует существование ровно одного экземпляра класса и предоставляет глобальную точку доступа к нему. В разделе C# тот же принцип «один экземпляр на приложение» часто реализуют через DI, а не через ручной статический класс — см. ASP.NET.
Где Singleton приносит пользу
- централизованный конфиг приложения;
- кэш в рамках процесса;
- клиент к редкому внешнему ресурсу;
- сервис, который обязан иметь единое состояние.
Ключевые требования
- закрытый конструктор;
- единственный экземпляр внутри класса;
- публичный доступ к экземпляру;
- корректная работа в многопоточном окружении.
Базовая безопасная реализация в C#
Почему этот вариант надежный:
Lazy<T>обеспечивает потокобезопасную ленивую инициализацию;sealedзакрывает наследование и упрощает модель объекта;- конструктор недоступен снаружи.
Пошаговый сценарий внедрения
Шаг 1. Определите, нужен ли единый экземпляр
Проверьте:
- объект хранит общее состояние;
- дублирование экземпляров создает риск рассинхрона;
- доступ требуется из нескольких модулей.
Шаг 2. Реализуйте класс по шаблону выше
Начните с минимального интерфейса и избегайте лишних обязанностей.
Шаг 3. Подключите в коде
var env = AppConfig.Instance.EnvironmentName;
AppConfig.Instance.SetEnvironment("Production");
Шаг 4. Добавьте тесты поведения
Проверьте:
- две ссылки указывают на один объект;
- изменение состояния через одну ссылку видно через другую;
- параллельный доступ не создает второй экземпляр.
Частые ошибки
- ленивый singleton без потокобезопасности;
- хранение бизнес-логики внутри singleton-класса;
- сильная связность всего приложения через глобальный объект;
- использование Singleton там, где подходит DI-контейнер.
Когда выбрать другой подход
В современных приложениях на ASP.NET Core чаще используют внедрение зависимостей и управляют временем жизни сервисов через контейнер:
AddSingleton— один экземпляр на приложение (аналог паттерна в DI);AddScoped— один экземпляр на HTTP-запрос;AddTransient— новый экземпляр при каждом запросе.
Подробнее о времени жизни — в ASP.NET — фреймворк и Web API.
Если проект уже на DI, регистрируйте сервис как singleton в Program.cs:
builder.Services.AddSingleton<IAppConfig, AppConfigService>();
Практическое задание
- Реализуйте singleton
AppSettingsStore. - Добавьте методы чтения и обновления одного параметра.
- Напишите тесты на идентичность экземпляра и потокобезопасность.
- Подготовьте короткий вывод: почему singleton подходит или не подходит для вашей задачи.
Рекомендую читать в энциклопедии
| Тема | Материал |
|---|---|
| Маршрут по C# | C# — о разделе |
| Классы, наследование, инкапсуляция | ООП в C# |
| Паттерн Singleton в теории | Порождающие паттерны |
| Обзор паттернов | Паттерны проектирования — о разделе |
DI и AddSingleton в ASP.NET |
ASP.NET — фреймворк |
| Регистрация сервисов в Web API | ASP.NET Web API |