← Назад к вопросам

В чём разница между Transient, Scoped и Singleton?

1.2 Junior🔥 272 комментариев
#Dependency Injection и IoC#Основы C# и .NET

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

В чём разница между Transient, Scoped и Singleton в ASP.NET Core DI?

В ASP.NET Core Dependency Injection (DI) существует три основных времени жизни (lifetime) служб: Transient, Scoped и Singleton. Понимание этих различий критично для корректного управления ресурсами, состояниями и многопоточностью в веб-приложениях.

Основные различия по времени жизни

1. Transient (Мгновенная)

  • Создание: Новый экземпляр создаётся каждый раз при запросе службы из контейнера зависимостей.
  • Область видимости: Кратковременная, существует только в рамках одного запроса на инъекцию.
  • Использование: Идеально для лёгких, не имеющих состояния (stateless) служб, где каждый вызов должен быть изолирован.
// Регистрация
services.AddTransient<IMyService, MyService>();

// Использование: каждый раз новый экземпляр
// В контроллере:
public class HomeController : Controller
{
    private readonly IMyService _service1;
    private readonly IMyService _service2;
    
    public HomeController(IMyService service1, IMyService service2)
    {
        // service1 и service2 - РАЗНЫЕ экземпляры
        _service1 = service1;
        _service2 = service2;
    }
}

2. Scoped (Область видимости)

  • Создание: Один экземпляр создаётся на область видимости (scope). В веб-приложении область видимости обычно соответствует одному HTTP-запросу.
  • Область видимости: Экземпляр живёт в рамках одной области (scope) и уничтожается при её завершении.
  • Использование: Подходит для служб, которым необходимо сохранять состояние в рамках одного запроса, например для DbContext в Entity Framework Core.
// Регистрация
services.AddScoped<IMyDbContext, MyDbContext>();

// Использование: один экземпляр на запрос
// В рамках одного HTTP-запроса все инъекции получат один и тот же экземпляр
public class OrderService : IOrderService
{
    private readonly IMyDbContext _dbContext;
    // В рамках одного запроса все сервисы получат одинаковый DbContext
}

3. Singleton (Одиночка)

  • Создание: Единственный экземпляр создаётся при первом запросе и существует на протяжении всего жизненного цикла приложения.
  • Область видимости: Глобальная, существует до остановки приложения.
  • Использование: Для глобальных, общих ресурсов, кешей, конфигураций, которые должны быть доступны всем запросам.
// Регистрация
services.AddSingleton<ICacheService, CacheService>();

// Использование: один экземпляр на всё приложение
// Этот экземпляр будет использоваться всеми запросами одновременно

Практические примеры и рекомендации

Безопасность потоков (Thread Safety)

  • Singleton службы должны быть потокобезопасными, так как к ним обращаются одновременно из множества потоков.
  • Scoped службы обычно не требуют полной потокобезопасности, так как один экземпляр используется только в рамках одного запроса.
  • Transient службы обычно не требуют потокобезопасности, если не используются в многопоточных сценариях.

Типичные сценарии использования

  • Transient: Сервисы для вычислений, валидаторы, мапперы (AutoMapper), простые фабрики
  • Scoped: Entity Framework Core DbContext, репозитории, сервисы бизнес-логики
  • Singleton: Кеши, клиенты для внешних API (если потокобезопасны), конфигурации, логгеры

Важные предупреждения и антипаттерны

// ОПАСНО: Singleton зависит от Scoped службы
services.AddSingleton<ISingletonService>(provider => 
{
    var scopedService = provider.GetRequiredService<IScopedService>();
    // Это вызовет проблему, так как Scoped служба будет "заперта" в Singleton
    return new SingletonService(scopedService);
});

// Решение: использовать фабрики или изменить время жизни

Производительность и управление ресурсами

  • Singleton наиболее эффективен по памяти и времени создания, но требует тщательного управления состоянием.
  • Transient может создавать нагрузку при частом создании тяжёлых объектов.
  • Scoped представляет баланс между изоляцией и производительностью для веб-приложений.

Визуализация различий

HTTP Запрос 1: [Transient A, Transient B] [Scoped X] [Singleton 1]
HTTP Запрос 2: [Transient C, Transient D] [Scoped Y] [Singleton 1]
HTTP Запрос 3: [Transient E, Transient F] [Scoped Z] [Singleton 1]

Выбор правильного времени жизни — это компромисс между изоляцией данных, производительностью и управлением памятью. Неправильный выбор может привести к утечкам памяти, проблемам с параллелизмом или непредсказуемому поведению приложения.

В чём разница между Transient, Scoped и Singleton? | PrepBro