I am utilizing nullable reference types in the C# nullable context.
I am taking a List<string>, then transforming it to a new List<string?> with a Select like so. I then filter out the nulls with a Where, but the underlying type is still List<string?>.
var strings = strings.
.Select(s => method.ThatReturnsNullableString(s))
.Where(s => s is not null)
.ToList();
When I try to use this as a List<string>, I get a CS8619 compiler warning. An easy solution is to use the ! null-forgiving operator and the warning goes away, but I try to use this as sparingly as possible.
Another solution is to use .Cast<string>, but I would assume this adds runtime overhead for no reason.
Have I not sufficiently proven to the compiler that the collection is of type string, or is there something I'm missing?
CodePudding user response:
.Where(s => s is not null) will suppress the null-only items and will keep items of type string?, so the result will be of type List<string?>.
Use .OfType<string>(), it will skip null values and casts string? to string, It's the equivalent to .Where(s => s is not null).Cast<string>().
strings = strings
.Select(s => method.ThatReturnsNullableString(s))
.OfType<string>()
.ToList(); // List<string>
CodePudding user response:
You could write an extension like, working example here
public static class EnumerableExtensions
{
public static IEnumerable<T> SkipNull<T, Y>(
this IEnumerable<Y> source,
Func<Y, T?> target)
{
foreach(var item in source)
{
var result = target(item);
if (result is not null)
{
yield return result;
}
}
}
}
You could use it like this,
public class Program
{
public static void Main()
{
var oddStrings = Enumerable
.Range(1, 100)
.SkipNull(Convert);
}
public static string? Convert(int value)
{
if(value % 2 == 0)
{
return null;
}
return value.ToString();
}
}
but, I would probably use OfType<string>, or if enumerating the sequence twice was a problem, write a standard function to process and filter the sequence in one pass. Unless of course, I was repeating this pattern.
