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

.NET Core中何时使用TryAddSingleton与AddSingleton?

TryAddSingleton vs AddSingleton: When to Use Which?

Great question—this is a common point of confusion when working with .NET Core's DI system, and the short answer is: no, TryAddSingleton isn't always "safer"—it depends entirely on your intent. Let's break down the differences and appropriate use cases:

Core Behavior Differences

First, let's recap the key behavior you noticed from decompiling:

  • AddSingleton<TService, TImplementation>(): Adds the service descriptor every time you call it, even if the same TService type is already registered. This means you can end up with multiple registrations for the same service type (when resolving IEnumerable<TService>, you'll get all of them; when resolving a single instance, the last registered one wins by default).
  • TryAddSingleton<TService, TImplementation>(): Only adds the descriptor if no registrations exist yet for TService. If there's any existing registration (even a different implementation), it does nothing.

When TryAddSingleton Is the Right Choice

Use this method when you want to:

  • Provide a default implementation without overriding existing ones: For example, if you're building a class library and want to register a service, but you don't want to overwrite any custom implementations the host application might have already registered. This respects the "host first" principle.
  • Avoid accidental duplicate registrations: If you're unsure whether a service might have been registered elsewhere (like in another library or a startup extension method), and you don't need multiple implementations, TryAddSingleton prevents redundant entries in the DI container.

When TryAddSingleton Is NOT the Right Choice

Don't use this method if:

  • You need to override an existing implementation: If your goal is to replace a default service with your own custom one, TryAddSingleton will fail here—if the service is already registered, your implementation won't be added. Instead, use AddSingleton (which appends your registration, making it the default resolved instance) or combine RemoveAll<TService>() with AddSingleton() to fully replace existing registrations.
  • You need multiple implementations of the same service: For scenarios like decorator patterns, or when you want to resolve all instances of a service type (via IEnumerable<TService>), TryAddSingleton only adds your implementation once. You'll need AddSingleton to register multiple distinct implementations.

Example Scenario

Suppose your app already has:

services.AddSingleton<IMyService, DefaultMyService>();
  • If you call services.TryAddSingleton<IMyService, CustomMyService>(): The CustomMyService won't be registered—resolving IMyService still gives DefaultMyService.
  • If you call services.AddSingleton<IMyService, CustomMyService>(): Resolving a single IMyService gives CustomMyService (last registration wins), and resolving IEnumerable<IMyService> gives both DefaultMyService and CustomMyService.

Key Takeaway

"Safe" is subjective here. TryAddSingleton is safe for avoiding unintended overrides, but it's unsafe if you need your implementation to be used. Always choose based on whether you want to augment, replace, or provide a fallback for a service registration.

内容的提问来源于stack exchange,提问作者Michael Freidgeim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:02:51