dotnet / dotnet/reactive

WhereNotNull operator

Open
#1,262 10 comments 3 reactions 0 assignees View on GitHub
[area] Rx
Dominant language
C#
Stars
7.2k
Forks
798
PR merge metrics
No merged PRs in 30d

Description

#### Feature request
> Which next library version (i.e., patch, minor or major)?

Minor, I suppose

> How commonly is this feature needed (one project, several projects, company-wide, global)?

Global

> Please describe the feature.

C#8 introduced nullability compiler features, which is slowly permeating codebases as people upgrade. One of the common clashes I've seen with Rx patterns, though, is the `WhereNotNull` style logic. This is a typical code snippet highlighting the friction:
```csharp
observable.Where(x => x != null).Subscribe(x => x!.DoStuff())
```

Here, the user checks that an item is not null, **but the following Rx operator is unaware that the item is now null safe**, and so has to add an `!` operator to "force it through".

In my own codebases, I have cleaned up this use case by adding the following extension:
```csharp
public static IObservable WhereNotNull(this IObservable source)
where T : class
{
return source
.Where(u => u != null)
.Select(u => u!);
}
```

A note on the fundamental concept: This operator takes in a nullable `T?`, but returns a non-nullable `T` type. This cleans up downstream operators that can now be certain the item is not null:

```csharp
observable.WhereNotNull().Subscribe(x => x.DoStuff())
```

However, **it has been noted that this `WhereNotNull` route introduces an extra `Select` statement that the original did not have.** This performance bite results in some people continuing to use the initial code snippets mentioned.

Overall, this seems like a fundamental concept to consider given the introduction of nullability concepts. **I'm hoping the Rx codebase might consider adding a dedicated official operator that could do the `T?` -> `T` shift in one fell swoop**, rather than leveraging two chained operators like my extension method does.

Essentially, it would be an alternative of `Where`, except the input generic would be nullable `T?`, while the output generic would be non-nullable `T`. The logic would do the null check, and produce signals where the input was not null, while migrating it to the non-null generic space for downstream operators.

I was going to dip into producing a PR to introduce this, but I wanted to open a discussion before putting in the work to confirm it's desirable in the first place.

Thanks for the consideration!

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.