You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core控制台应用中AddScoped与AddSingleton的区别

在控制台应用中AddScoped与AddSingleton的行为差异

在控制台这类没有默认请求上下文的应用里,AddScoped和AddSingleton的核心差异体现在生命周期触发方式、实例复用范围、资源释放时机三个方面:

1. 生命周期触发与实例创建规则

  • AddSingleton:第一次从服务容器获取实例时创建,之后整个应用生命周期内复用同一个实例,不管从根容器还是子作用域获取,拿到的都是同一个对象。
  • AddScoped:必须手动创建IServiceScope(通过serviceProvider.CreateScope())才能获取合规的实例。如果直接从根容器获取Scoped服务,会触发.NET的警告,且实例会绑定到根容器的生命周期(等同于Singleton)——这是反模式,容易引发资源泄漏问题,绝不推荐。

2. 实例复用范围

  • AddSingleton:全局唯一,所有代码路径获取的都是同一个实例,哪怕跨多个手动创建的作用域。
  • AddScoped:仅在单个手动创建的作用域内复用。不同作用域中获取的Scoped服务是完全独立的实例。

3. 资源释放时机

  • AddSingleton:只有当应用程序关闭、根服务容器被释放时,才会销毁实现了IDisposable的Singleton实例。
  • AddScoped:当调用scope.Dispose()(通常通过using语句自动执行)时,该作用域内所有Scoped实例都会被立即释放,无需等待应用关闭,适合管理需要及时回收的资源。

代码示例

// 注册服务
var services = new ServiceCollection();
services.AddScoped<SomeServiceClass>();
services.AddSingleton<AnotherServiceClass>();
var provider = services.BuildServiceProvider();

// 测试Scoped服务:同一作用域内实例复用
using (var scope = provider.CreateScope())
{
    var scoped1 = scope.ServiceProvider.GetRequiredService<SomeServiceClass>();
    var scoped2 = scope.ServiceProvider.GetRequiredService<SomeServiceClass>();
    Console.WriteLine(scoped1.GetHashCode() == scoped2.GetHashCode()); // 输出 True
}

// 不同作用域的Scoped实例独立
using (var anotherScope = provider.CreateScope())
{
    var scoped3 = anotherScope.ServiceProvider.GetRequiredService<SomeServiceClass>();
    Console.WriteLine(scoped3.GetHashCode() != scoped1.GetHashCode()); // 输出 True
}

// 测试Singleton服务:全局复用
var singleton1 = provider.GetRequiredService<AnotherServiceClass>();
var singleton2 = provider.GetRequiredService<AnotherServiceClass>();
Console.WriteLine(singleton1.GetHashCode() == singleton2.GetHashCode()); // 输出 True

内容的提问来源于stack exchange,提问作者Subin Jacob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:08:16