.NETのDIで利用するサービスを登録するメソッドがあります。 名前がAddから始まるメソッド、TryAddから始まるメソッド、TryAddEnumerableメソッドの違いがよく分かっていなかったので軽くまとめたいと思います。 (この投稿ではAddTransientAddScopedAddSingletonといったサービスの有効期間についてはふれません。)

それぞれのサービス登録メソッドの違いは、同じサービス(の実装)を複数登録したときに登録できるかどうかです。 TryAdd系メソッドは同じサービスに対して複数の実装を登録できないのに対して、TryAddEnumerableメソッドは同じサービスに対して異なる実装であれば複数登録できます。

メソッド 同じサービス(の実装)を複数登録したときの動き
Add系メソッド 登録できる
TryAdd系メソッド 登録できない
TryAddEnumerableメソッド 異なる実装であれば登録できる

例としてScopedを扱って下記メソッドの違いを確認できるサンプルコードを残しておきます。

まず、サンプルで利用するインターフェイスと実装クラスです。

public interface IService {
}

public class ServiceA : IService {
}

public class ServiceB : IService {
}

AddScopedメソッド

AddScopedメソッド(AddTransientAddSingletonを含めたAdd系メソッド)は、同じサービスの実装を複数登録できます。

var services = new ServiceCollection();
services.AddScoped<IService, ServiceA>();

// 同じサービスを複数登録できる
services
	// 同じサービスの同じ実装
	.AddScoped<IService, ServiceA>()
	// 同じサービスの別の実装
	.AddScoped<IService, ServiceB>();

foreach (var service in services) {
	Console.WriteLine(service.ImplementationType?.Name);
}
// ServiceA
// ServiceA
// ServiceB

TryAddScopedメソッド

TryAddScopedメソッド(TryAddTransientTryAddSingletonを含めたTryAdd系メソッド)は、同じサービスを複数登録できません。

var services = new ServiceCollection();
services.AddScoped<IService, ServiceA>();

// 同じサービスを複数登録できない
services.TryAddScoped<IService, ServiceA>();
services.TryAddScoped<IService, ServiceB>();

foreach (var service in services) {
	Console.WriteLine(service.ImplementationType?.Name);
}
// ServiceA

TryAddEnumerableメソッド

TryAddEnumerableメソッドは、同じサービスの同じ実装は登録できませんが、別の実装であれば登録できます。

var services = new ServiceCollection();
services.AddScoped<IService, ServiceA>();

// 同じ実装は登録できない
services.TryAddEnumerable(ServiceDescriptor.Scoped<IService, ServiceA>());
// 別の実装であれば登録できる
services.TryAddEnumerable(ServiceDescriptor.Scoped<IService, ServiceB>());

foreach (var service in services) {
	Console.WriteLine(service.ImplementationType?.Name);
}
// ServiceA
// ServiceB

参考