Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] WhereNotNull & SelectNotNull #784

Closed
bram209 opened this issue Jan 5, 2021 · 5 comments
Closed

[Proposal] WhereNotNull & SelectNotNull #784

bram209 opened this issue Jan 5, 2021 · 5 comments

Comments

@bram209
Copy link

bram209 commented Jan 5, 2021

With C# 8 nullability feature it would be nice to be able to easily filter out null values.
I always use

        <Nullable>enable</Nullable>
        <WarningsAsErrors>nullable</WarningsAsErrors>

For strict nullability warnings. Would be nice if we can have linq extensions that can automatically remove all null values and return a sequence of a non-nullable type.

     public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> enumerable) =>
            enumerable.Where(e => e != null)!;
    IEnumerable<Person?> nullableList = new List<Person?> { new("Foo"), null, new("Bar")};
    IEnumerable<Person> values = nullableList.WhereNotNull();
    Debug.Assert(values.Count() == 2);
@bram209 bram209 changed the title [Proposal] WhereNotNull() [Proposal] WhereNotNull() & SelectNotNull() Jan 5, 2021
@bram209 bram209 changed the title [Proposal] WhereNotNull() & SelectNotNull() [Proposal] WhereNotNull() & SelectNotNull() Jan 5, 2021
@atifaziz atifaziz changed the title [Proposal] WhereNotNull() & SelectNotNull() [Proposal] WhereNotNull & SelectNotNull Jan 5, 2021
@atifaziz
Copy link
Member

atifaziz commented Jan 5, 2021

I believe that this is a duplicate of #609, where I have presented arguments why Choose is what you want, better, more powerful and more generic. In short, by breaking down the problem another way, you can use Choose directly:

IEnumerable<Person?> nullableList = new List<Person?> { new("Foo"), null, new("Bar")};
IEnumerable<Person> values = nullableList.Choose(Nullable.Deconstruct);
Debug.Assert(values.Count() == 2);

record Person(string Name);
    
static partial class Nullable
{
    public static (bool HasValue, T Value) Deconstruct<T>(T? nullable) =>
        nullable is not null ? (true, nullable) : default;
}

Notice how the signature of Choose also adapts correctly instead of masquerading through the null-forgiving operator (!). Choose has two type parameters: T and TResult. In the example above, T is Person? and TResult is Person and you don't need any ! to change some T? into T.

I'll close this for now as a duplicate, but open to reconsidering if I've overlooked something.

@atifaziz atifaziz closed this as completed Jan 5, 2021
@skarllot
Copy link

skarllot commented Nov 18, 2023

@atifaziz What you think of providing a WhereNotNull extension as a shortcut of using Choose and implementing the Desconstruct method?

@atifaziz
Copy link
Member

atifaziz commented Nov 18, 2023

What you think of providing a WhereNotNull extension as a shortcut of using Choose and

@skarllot Why have another way to do the same thing?

implementing the Desconstruct method?

It doesn't belong in MoreLINQ since it generally extends any type T whereas this library should only be extending sequential family of types like IEnumerable<> & IAsyncEnumerable<>.

@skarllot
Copy link

@atifaziz because it is a very common use case and avoid repeating the same code over and over.

And about the null forgiving, the proposed Desconstruct is masquerading the null too as it returns default that returns null too, but it is not detected by compiler.

@atifaziz
Copy link
Member

@atifaziz because it is a very common use case and avoid repeating the same code over and over.

Right, but MoreLINQ is not a convenience library of small helpers for common code. See the discussion in PR #1001 for some background.

And about the null forgiving, the proposed Desconstruct is masquerading the null too as it returns default that returns null too, but it is not detected by compiler.

True, but if you get a (false, _) then using the second half of the couple is undefined and at the risk of the user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants