C
C#14mo ago
Hugh

❔ ✅ Best way to just get not null values from a collection of possibly null values

I've got a List<MyType?>, and I want to filter out all null values and get a List<MyType back. Which of these is preferable (and more idiomatic) for this, or is there a 3rd better way:
List<MyType> validTypes = possiblyNullTypes.Where(item => item is not null).Cast<MyType>().ToList();
List<MyType> validTypes = possiblyNullTypes.Where(item => item is not null).Select(item => item!).ToList();
List<MyType> validTypes = possiblyNullTypes.Where(item => item is not null).Cast<MyType>().ToList();
List<MyType> validTypes = possiblyNullTypes.Where(item => item is not null).Select(item => item!).ToList();
Thanks
20 Replies
Henkypenky
Henkypenky14mo ago
just
var x = list.Where(p => p is not null).ToList();
var x = list.Where(p => p is not null).ToList();
should suffice
Hugh
Hugh14mo ago
If I do that, x is still a List<MyType?>, though, even though I know that there aren't any null values in it And then when I iterate over it later on, my IDE will still want me to check for null
Henkypenky
Henkypenky14mo ago
ah okay then define the type explicitly and cast
Hugh
Hugh14mo ago
So Cast<MyType>() over Select(item => item!)
Thinker
Thinker14mo ago
Important distinction, is MyType a struct?
Hugh
Hugh14mo ago
it's a class Good point
Thinker
Thinker14mo ago
right
MODiX
MODiX14mo ago
Henkypenky#4865
REPL Result: Success
List<int?> list = new() { 1, 2, 3, null, 5, 6, 7, null };

var x = list.Where(x => x is not null).Cast<int>().ToList();

foreach (var item in x)
{
Console.WriteLine(item);
}
List<int?> list = new() { 1, 2, 3, null, 5, 6, 7, null };

var x = list.Where(x => x is not null).Cast<int>().ToList();

foreach (var item in x)
{
Console.WriteLine(item);
}
Console Output
1
2
3
5
6
7
1
2
3
5
6
7
Compile: 711.182ms | Execution: 130.866ms | React with ❌ to remove this embed.
Thinker
Thinker14mo ago
Then you can do what @Henkypenky said will work and you can safely ignore any null warnings.
Henkypenky
Henkypenky14mo ago
yeah Cast is ...
Doombox
Doombox14mo ago
ToList also allows you to explicitly set the type, .Where(x => x is not null)!.ToList<string>(); would work with the null forgiveness just thrown in there
Thinker
Thinker14mo ago
as long as you slap a ! at the end to signify that you know it's valid and null-safe
Doombox
Doombox14mo ago
var strings = new List<string?>();
var res = strings.Where(x => x is not null).ToList<string>();
var strings = new List<string?>();
var res = strings.Where(x => x is not null).ToList<string>();
that will give you a nullability warning but yeah you can just forgive it so, dunno if I'd bother with the cast as well when ToList allows you to specify the type, but that's up to you always bump into this, so weird that the static analysis can't detect this with any reliability catshrug
Henkypenky
Henkypenky14mo ago
it's also a semantics thing right, cause the type is declared as nullable, you just filtered the collection, you know nothing is null, but yeah as Task says the analyzers don't always get it right, they have to cover a lot of basis
Doombox
Doombox14mo ago
just one of those annoying little nullability quirks you learn to live with
Henkypenky
Henkypenky14mo ago
indeed
Hugh
Hugh14mo ago
Thanks all - this has been helpful How about if I didn't specifically want a List<MyType>, but just wanted to get an IEnumerable<MyType> instead? yeah - it certainly seems that this should be able to be dealt with
Doombox
Doombox14mo ago
just .Cast<Type>(); without the ToList() call at all
Hugh
Hugh14mo ago
👍 Thanks - appreciate the help here
Accord
Accord14mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.