TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2965 2.85K
День 2464. #ЗаметкиНаПолях
Потокобезопасная Инициализация с Помощью LazyInitializer
Хотя Lazy<T> является основным решением для ленивой инициализации в .NET, существует менее известная альтернатива, которая может быть более эффективной в некоторых сценариях: LazyInitializer.EnsureInitialized.

Этот статический метод обеспечивает потокобезопасную инициализацию с рядом ключевых характеристик:
- Только ссылочные типы: работает только с классами, но не со значениями.
- Обнаружение на основе NULL: использует значение NULL для определения необходимости инициализации.
- Эффективное использование памяти по сравнению с System.Lazy<T>: не требуется дополнительный объект-обёртка.

Метод предлагает несколько перегрузок для различных сценариев:
Sample? _instance = null;

// Инициализация через конструктор по умолчанию
var instance =
LazyInitializer.EnsureInitialized(ref _instance);

// Фабричный метод
var instance =
LazyInitializer.EnsureInitialized(
ref _instance,
() => new Sample()
);

// Фабричный метод вызывается 1 раз, даже если нескольким потокам требуется инициализация
var syncLock = new object();
var instance =
LazyInitializer.EnsureInitialized(
ref _instance,
ref syncLock,
() => new Sample()
);


Замечания по потокобезопасности
По умолчанию LazyInitializer.EnsureInitialized ведёт себя как LazyThreadSafetyMode.PublicationOnly:
Несколько потоков могут создавать экземпляры одновременно. Сохраняется только первое успешное назначение. Остальные экземпляры отбрасываются.
Для строгой потокобезопасности используйте перегрузку с блокировкой синхронизации, чтобы гарантировать, что фабричный метод будет выполнен только один раз.

Внутренняя реализация этого аналогична следующему коду:
var instance = Volatile.Read(ref _instance) ??
Interlocked.CompareExchange(
ref _instance,
new Sample(),
null);


Преимущества
Главное преимущество перед Lazy<T> — вместо хранения объекта-обёртки Lazy<T> вы напрямую используете целевой экземпляр. Также это снижает затраты памяти, экономя одно поле на каждое лениво инициализированное значение.

Источник: https://www.meziantou.net/thread-safe-initialization-with-lazyinitializer.htm
  • 👍 15
More from @netdeveloperdiary
  1. Sep 30, 2026Post #3356
  2. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  3. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  4. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  5. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  6. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →