runtime: [Analyzer Proposal]: Convert argument null checks to ArgumentNullException.ThrowIfNull
In support of the now-defunct !!
feature, @RikkiGibson built into a Roslyn an analyzer/fixer that found constructs like:
void M(string arg)
{
if (arg is null)
throw new ArgumentNullException(arg);
...
}
and replaced them with:
void M(string arg!!)
{
...
}
Now that !!
is no more, we should salvage this work and transform it to instead use ArgumentNullException.ThrowIfNull
if available:
void M(string arg)
{
ArgumentNullException.ThrowIfNull(arg);
...
}
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 17
- Comments: 21 (17 by maintainers)
Can we also modify the existing “Add null check” quickfix in Visual Studio so that it has an option for generating an
ArgumentNullException.ThrowIfNull
call? 🙂The “Add null check” quickfix currently looks like this:
Ideally, the quickfix would also have an option for generating a call to
ArgumentNullException.ThrowIfNull
, so that the resulting code looks like this:(I originally posted this at https://github.com/dotnet/roslyn/issues/61181, and someone directed me here 🙂)
It might be good to check whether/when the boxing is elided by JIT in such scenarios.
Video
Make sense as proposed
We feel like this would also approve the other throw helpers:
ObjectDisposedException.ThrowIf
ArgumentException.ThrowIfNullOrEmpty
@CyrusNajmabadi and I chatted offline and we think that a pared-down version of the feature might be appropriate here.
We think that it might be most appropriate to handle this by:
param ?? throw
” independently from "preferThrowIfNull(param)
.We also have concerns about the perf benefits that are suggested to be present when the user uses a helper method to throw for an uncommon case, versus using a
throw
directly in an uncommon code path in the same method. That’s specifically the fact that methods which directly includethrow
can’t be inlined, right?It feels like it would be ideal to adjust the runtime so it is able to inline methods which contain
throw
, so that large amounts of existing code can benefit. To some extent it’s concerning to ask users to adjust their coding patterns to accommodate what seems like an internal behavior detail of the runtime.I’m going to look at this one…
aspnetcore is interested in this analyzer. We have a lot of source code with traditional null checks. We’d use the analyzer+fixer to automate updating our repo source - https://github.com/dotnet/aspnetcore/issues/43482
or, alternatively, the runtime should look specifically for
if (x is null) throw ArgumentNullException(nameof(x))`` and treat that identically to whatever it generates for
ArgumentNullException.ThrowIfNull(x)`. Basically, it’s not a pit of success for these two idiomatic expressions to have such different perf outcomes.I think this is a good idea, and that this would be done by adjusting the existing analyzer/fixer in the Roslyn IDE code style layer. Tagging @CyrusNajmabadi for a second opinion.