Runtime: SelectNonNull extension method

Created on 31 Jan 2018  路  11Comments  路  Source: dotnet/runtime

Could we have this in System.Linq ?

```C#
public static IEnumerable SelectNonNull(this IEnumerable items,Func func) where V : class
{
foreach(var item in items)
{
var value = func(item);
if(value != null)
yield return value;
}
}

public static IEnumerable SelectNonNull(this IEnumerable items,Func func) where V : struct
{
foreach(var item in items)
{
var value = func(item);
if(value.HasValue)
yield return value.Value;
}
}
```

I don't know what name it should but this extension method is convenient

api-suggestion area-System.Linq

Most helpful comment

Eliminating the need for ! is what makes this combination valuable

I don't think adding new LINQ APIs is the right way to address this. From my perspective, it should be done via language/compiler support.
https://github.com/dotnet/roslyn/issues/39586
https://github.com/dotnet/csharplang/issues/3868
cc: @jcouv

All 11 comments

Thanks Thaina. It would be helpful to follow https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md

Also, it would be helpful to mention the most common use cases, and why it is specially needed in the framework, and not as a helper library to a few users who might use it.

SelectNonNull has always struck me as ugly. .Select(...).NonNull() is more interesting to me. More generally, it could be .Select(...).Except(null) where it's a more efficient single-item version of the existing Except.

@jnm2 Interesting. .ExceptNull() could be alternative

But Except(null) is not possible. Because Except(null) will match Except((IEnumerable)null). We need new name for it

And it can't convert nullable to struct, which is the point of this proposal

Also should we .Select(func).ExceptNull() or just allow .ExceptNull(func) ?

Why is this not just:
C# .Select(func).Where(c => c != null)
?

@stephentoub @Thaina seemed particularly interested in the unwrapping of nullable values (second overload).

Equivalent of that one would be .Select(func).Where(n => n != null).Select(n => n.Value)

I have a .Values() extension method which shows up for enumerables of nullables and returns an enumerable of the inner value type, and I do find that quite ergonomic.

@stephentoub It obviously shorter and reduce number of delegates

It obviously shorter and reduce number of delegates

Yes, that's true for any LINQ usage of multiple operators; you could always create a new operator that represented the combination. I'm not seeing why this particular combination is so valuable and generally in need by many developers that it would warrant a dedicated method.

@stephentoub Because I think this is most common logic. To select something and also filtering at the same time. Without the need to pollute code with .Where(n => n != null) everywhere we could just indicate that we don't need null

If we have a NonNull (or FilterOutNull?), we can convert IEnumerable<int?> into IEnumerable<int>.
I want to processing list of nullable reference types more easily .

https://docs.microsoft.com/ja-jp/dotnet/csharp/tutorials/nullable-reference-types

I ran into the same need when converting code base of a project to NRT.

A pattern that keeps appearing in my code is:

public IEnumerable<Guid> GetAllGuids1(IEnumerable<SomeClass> instances)
{
    return instances
        .Where(x => x.SomeGuid.HasValue)
        .Select(x => x.SomeGuid!.Value);
}

public class SomeClass
{
    public Guid? SomeGuid { get; set; }
    public string? Name { get; set; }
}

Couldn't find anything in the framework which would allow to easily convert from T? to T without the use of null-forgiving operator. Eliminating the need for ! is what makes this combination valuable. @stephentoub

Eliminating the need for ! is what makes this combination valuable

I don't think adding new LINQ APIs is the right way to address this. From my perspective, it should be done via language/compiler support.
https://github.com/dotnet/roslyn/issues/39586
https://github.com/dotnet/csharplang/issues/3868
cc: @jcouv

Was this page helpful?
0 / 5 - 0 ratings