|
| 1 | +--- |
| 2 | +title: "Breaking change: Fix issues in GetKeyedService() and GetKeyedServices() with AnyKey" |
| 3 | +description: "Learn about the breaking change in .NET 10 where GetKeyedService() and GetKeyedServices() behavior changed when using KeyedService.AnyKey as the lookup key." |
| 4 | +ms.date: 11/19/2025 |
| 5 | +ai-usage: ai-assisted |
| 6 | +--- |
| 7 | + |
| 8 | +# Fix issues in GetKeyedService() and GetKeyedServices() with AnyKey |
| 9 | + |
| 10 | +The behavior of the <xref:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions.GetKeyedService(System.IServiceProvider,System.Type,System.Object)> and <xref:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions.GetKeyedServices(System.IServiceProvider,System.Type,System.Object)> methods in the `Microsoft.Extensions.DependencyInjection` library was updated to address inconsistencies in handling the <xref:Microsoft.Extensions.DependencyInjection.KeyedService.AnyKey?displayProperty=nameWithType> registration. Specifically, `GetKeyedService()` now throws an exception when you attempt to resolve a single service using `KeyedService.AnyKey` as the lookup key, and `GetKeyedServices()` (plural) no longer returns `AnyKey` registrations when queried with `KeyedService.AnyKey`. |
| 11 | + |
| 12 | +## Version introduced |
| 13 | + |
| 14 | +.NET 10 |
| 15 | + |
| 16 | +## Previous behavior |
| 17 | + |
| 18 | +Previously, calling `GetKeyedService()` with `KeyedService.AnyKey` returned a service registration associated with `AnyKey`. This behavior was inconsistent with the intended semantics, as `AnyKey` is meant to represent a special case of keyed services rather than a specific registration. |
| 19 | + |
| 20 | +Calling `GetKeyedServices()` with `KeyedService.AnyKey` returned all registrations for `AnyKey`. This behavior was also inconsistent with the intended semantics, as `AnyKey` is not meant to enumerate all keyed services. |
| 21 | + |
| 22 | +## New behavior |
| 23 | + |
| 24 | +Starting in .NET 10, calling `GetKeyedService()` with `KeyedService.AnyKey` throws an <xref:System.InvalidOperationException>. This ensures that `AnyKey` can't be used to resolve a single service, as it's intended to represent a special case rather than a specific key. |
| 25 | + |
| 26 | +```csharp |
| 27 | +var service = serviceProvider.GetKeyedService(typeof(IMyService), KeyedService.AnyKey); |
| 28 | +// Throws InvalidOperationException: "Cannot resolve a single service using AnyKey." |
| 29 | +``` |
| 30 | + |
| 31 | +Additionally, calling `GetKeyedServices()` with `KeyedService.AnyKey` no longer returns registrations for `AnyKey`. Instead, it adheres to the updated semantics where `AnyKey` is treated as a special case and doesn't enumerate services. |
| 32 | + |
| 33 | +```csharp |
| 34 | +var services = serviceProvider.GetKeyedServices(typeof(IMyService), KeyedService.AnyKey); |
| 35 | +// Returns an empty collection. |
| 36 | +``` |
| 37 | + |
| 38 | +## Type of breaking change |
| 39 | + |
| 40 | +This change is a [behavioral change](../../categories.md#behavioral-change). |
| 41 | + |
| 42 | +## Reason for change |
| 43 | + |
| 44 | +The previous behavior of `GetKeyedService()` and `GetKeyedServices()` with `KeyedService.AnyKey` was inconsistent with the intended semantics of `AnyKey`. The changes were introduced to ensure that `AnyKey` is treated as a special case and can't be used to resolve a single service, and to prevent `GetKeyedServices()` from returning `AnyKey` registrations when queried with `AnyKey`. These updates improve the predictability and correctness of the `Microsoft.Extensions.DependencyInjection` library's behavior when working with keyed services. For more details, see the [pull request](https://github.com/dotnet/runtime/pull/113137) and the associated [merge commit](https://github.com/dotnet/runtime/commit/deee462fc8421a7e18b8916eb5a5eacb9d09169d). |
| 45 | + |
| 46 | +## Recommended action |
| 47 | + |
| 48 | +If you use `GetKeyedService()` or `GetKeyedServices()` with `KeyedService.AnyKey`, review your code and update it to use specific keys instead of `AnyKey`. |
| 49 | + |
| 50 | +For `GetKeyedService(KeyedService.AnyKey)`, replace calls to `GetKeyedService()` with `KeyedService.AnyKey` with specific keys or alternative logic to handle service resolution. |
| 51 | + |
| 52 | +For `GetKeyedServices(KeyedService.AnyKey)`, replace calls to `GetKeyedServices()` with `KeyedService.AnyKey` with calls that use specific keys, or update your logic to enumerate only the services you intend to retrieve. |
| 53 | + |
| 54 | +## Affected APIs |
| 55 | + |
| 56 | +- <xref:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions.GetKeyedService(System.IServiceProvider,System.Type,System.Object)?displayProperty=fullName> |
| 57 | +- <xref:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions.GetKeyedServices(System.IServiceProvider,System.Type,System.Object)?displayProperty=fullName> |
0 commit comments