[Design Discussion] Standardise on `(X)GetService(typeof(X))` or `GetService(typeof(X)) as X`
See original GitHub issueThere’s currently a 50-50 split between the following pattern:
IServiceProvider provider = ...;
IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService))
if (edSvc != null)
{
// Continue
}
and
if (provider.GetService(typeof(IWindowsFormsEditorService) is IWindowsFormsEditorService edSvc)
{
// Continue
}
The former throws InvalidCastException if the service is invalid (e.g. returns new object()) while the latter lets this pass through.
From #760
I have a couple of comments as I think the use of as/is has numerous benefits
- Clears up confusion as to what happens when the service is null - will this throw
InvalidCastExceptionorNullReferenceException. Actually, it’s neither - it returns null - but the as/is pattern avoids this confusion. - Most importantly, we can use the C# construct if (variable is Type variableAsType) which lets us made code more readable, express intent better etc.
It’s essentially my view is that it was the throwing InvalidCastException behavior is an oversight that didn’t account for an edge case. If we had a deliberate policy, then this in the case we’d use the force cast rather than the as cast across winforms, but we don’t. The intent is to get an object of that type. In each case we check for null so we understand that the provider can return an invalid service. In some cases we’ve accounted for where the provider returns a non-interface service, in others we haven’t. It’s my opinion that we should standardise on the latter.
Note that it could be considered a breaking change (throwing exception vs. not before) to use the force cast where an as cast was used previously. You could argue that things that failed/threw before would now succeed, but I believe this is not considered as breaking as the former.
/cc @weltkante @zsd4yr
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (8 by maintainers)

Top Related StackOverflow Question
I’ve seen
ascasts used inappropriately a lot, including in the .NET Framework codebase. Most prominentlyasfollowed by a member access, which will result in NRE instead of ICE. When I had the chance to talk to people who write such code it’s usually the argument “its more readable” than the forced cast when the type follows the expression. They ignore (or arent’ aware of) what the cast does and that it prodcues less debuggable exceptions.Because there is so little awareness of “using the right cast for its side effects” vs. “using the pretty cast for readability” I’d not take the cast itself as strong evidence that it is the right thing to do.
You check for null because providing an interface is optional. Providing a wrong interface is a bug, like passing the wrong argument, which you usually want to find via exceptions. Debugging a first chance exception is much easier than debugging why something doesn’t happen. It’s not a mistake made often so its probably not worth throwing explicit exceptions for it. Anyways, the type you request represents a contract and you ask the service providier if he implements that contract. You go through the interface and don’t cast the service provider itself to allow him to implement the contract on another object.
Unfortunately this interface was defined before generics existed, otherwise this would have been
T GetService<T>()to not allow this ambiguity.There is precedence in ASP.NET Core (link to doc and src) to use the throwing variant, by providing the generic method as an extension method and directly implementing the force cast. You could reference
Microsoft.Extensions.DependencyInjection.Abstractions.dllor implement an internal version of that extension to avoid having to do the cast on every call site.I think we’re maybe talking about two differnet things.
nulland don’t throw(MyType)GetService(OtherType)- this should be a bug and we should fail.