Напишите пример реализации Singleton на C#
Что проверяют
Здесь смотрят не на умение вспомнить паттерн, а на то, как быстро вы уходите от наивной реализации к рабочей и что говорите про сам экземпляр после его создания. Вопрос почти всегда переходит в разговор о многопоточности.
Как отвечать
Покажите вариант с двойной проверкой и проговорите роль каждой части:
public sealed class Cache
{
private static volatile Cache? _instance;
private static readonly object _lock = new();
private Cache() { }
public static Cache Instance
{
get
{
if (_instance is null)
lock (_lock) { _instance ??= new Cache(); }
return _instance;
}
}
}sealed запрещает наследование, приватный конструктор закрывает создание снаружи, volatile не даёт увидеть недостроенный объект, внешняя проверка убирает блокировку с горячего пути. Дальше честно добавьте, что в боевом коде это пишут короче: статическое поле только для чтения либо Lazy<T>, оба варианта потокобезопасны без единого lock.
Отдельно стоит сказать вещь, которую забывают: единственность экземпляра не делает его потокобезопасным. Если внутри изменяемое состояние, его защищают сами, через ConcurrentDictionary, Interlocked или блокировку.
Где спотыкаются
Кладут в конструктор побочные эффекты: чтение конфигурации, поход в сеть или в базу. Исключение из статического инициализатора превращается в TypeInitializationException, и тип остаётся мёртвым до перезапуска процесса, а исходная причина прячется во внутреннем исключении.
Предлагают singleton с параметрами, метод вида «получить экземпляр с такой конфигурацией». Параметр учитывается только при первом вызове, все последующие его молча игнорируют, и получается источник трудноуловимых ошибок.
Вешают IDisposable на класс с единственным экземпляром и не могут ответить, кто и когда зовёт освобождение ресурсов. Заодно не проговаривают цену для тестов: состояние живёт между тестами, порядок их выполнения начинает влиять на результат.