Is there a convenient way to filter a sequence of C# 8.0 nullable references, retaining only non-nulls?
Unfortunately you will have to tell the compiler that you know more about the situation than it does.
One reason would be that the Where
method has not been annotated in a way that lets the compiler understand the guarantee for non-nullability, nor is it actually possible to annotate it. There might be a case for having additional heuristics added to the compiler to understand some basic cases, like this one, but currently we do not have it.
As such, one option would be to use the null forgiving operator, colloquially known as the "dammit operator". You touch upon this yourself, however, instead of sprinkling exclamation marks all over the code where you use the collection, you can instead tuck on an additional step on producing the collection which, at least to me, makes it more palatable:
var nonNullItems = items.Where(item => item != null).Select(s => s!);
This will flag nonNullItems
as IEnumerable<string>
instead of IEnumerable<string?>
, and thus be handled correctly in the rest of your code.
I think you'll have to help the compiler in either one way or another. Calling .Where()
is never safe of returning not-null. Maybe Microsoft could add some logic to determine basic scenarios like yours, but AFAIK that's not the situation right now.
However, you could write a simple extension method like that:
public static class Extension
{
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> o) where T:class
{
return o.Where(x => x != null)!;
}
}
I don't know if this answer meets the criteria for your 3rd bullet point, but then your .Where()
filter does not either, so...
Replace
var nonNullItems = items.Where(item => item != null)
with
var nonNullItems = items.OfType<string>()
This will yield an inferred type of IEnumerable<string>
for nonNullItems
, and this technique can be applied to any nullable reference type.