3 ms·
As a side note: please avoid, as much as possible, putting `.Select(..)` before `.Where(..)`. You are wasting CPU cycles and memory space by forcing LINQ to map
by mrcsharp 1y ago
As a side note: please avoid, as much as possible, putting `.Select(..)` before `.Where(..)`. You are wasting CPU cycles and memory space by forcing LINQ to map all the items and then filtering on the mapped value.
In most situations, you should be able to filter on the source enumerable before mapping making the whole thing more efficient.
Additionally, that `.Cast<TR>(..)` at the end should have been a dead giveaway that you are going down the wrong path here. You are incurring even more CPU and Memory costs as the `.Cast<TR>(..)` call will now iterate through all the items needlessly.[1]
Also, the design of this this method doesn't seem to make much difference to me anyways:
```
var strs = source.SelectNotNull(it => it);
```
vs
```
var strs = source.Where(it => it != null);
```
A lot of other LINQ extension methods allow you to pass in a predicate expression that will be executed on the source enumerable:
```
var str = source.First(it => it != null);
```
[1] https://source.dot.net/#System.Linq/System/Linq/Cast.cs,152b93d25e224365 https://source.dot.net/#System.Linq/System/Linq/Cast.cs,152b...
- LtWorf 1y agoIf I was able to write a simple optimiser for relational algebra, I'm sure microsoft engineers can come up with something :D
- angrysaki 1y ago>Also, the design of this this method doesn't seem to make much difference to me anyways: ``` var strs = source.SelectNotNull(it => it); ``` vs ``` var strs = source.Where(it => it != null); ``` Wouldn't the first be IEnumerable<TR> and the second be IEnumerable<TR?> I imagine that's the main driver for creating SelectNotNull, so that you get the nonnullable type out of the Linq query
- mrcsharp 1y ago> I imagine that's the main driver for creating SelectNotNull Sure. And now we are fighting the compiler and in the process writing less efficient code. The compiler gives us a way to deal with this situation. It is all about being absolutely clear with intentions. Yes, Where(..) in my example would return IEnumerable<TR?> but then in subsequent code I can tell the compiler that I know for a fact that TR? is actually TR by using the null forgiving operator (!).
- angrysaki 1y ago>The compiler gives us a way to deal with this situation. It is all about being absolutely clear with intentions. Yes, Where(..) in my example would return IEnumerable<TR?> but then in subsequent code I can tell the compiler that I know for a fact that TR? is actually TR by using the null forgiving operator (!). I guess that seems way less clear with intentions to me. If I have an array of potentially null types and I want to filter out the not nulls, I'd much rather have an operation that returns a T[] vs a T?[]. I should also note that I also have a "IEnumerable<T> WhereNotNull(IEnumerable<T>?)" function in my codebase, but I implemented it using a foreach/yield which doesn't suffer from the extra Cast<>()
- meow_cat 1y agoI actually use OfType<TR> to remove null elements as suggested by the doc. https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.oftype?view=net-9.0 https://learn.microsoft.com/en-us/dotnet/api/system.linq.enu... Performance-wise, where is this situated?