morelinq / MoreLINQ

Extensions to LINQ to Objects
https://morelinq.github.io/
Apache License 2.0
3.63k stars 409 forks source link

FullGroupJoin with null keys #1000

Open fhucko opened 1 year ago

fhucko commented 1 year ago

I expected that FullGroupJoin will return all items, even those with null keys, but somehow FullGroupJoin does not return null keys. I tried implementing custom comparer, but it did not help.

So to fix this, I am currently using "clever hack" for key functions using tuple: p => (p.Id, true). This treats null keys as non-null. A record would work too I guess.

Is there any more clear way to make FullGroupJoin not ignore null keys?

Null keys do not work: https://dotnetfiddle.net/iefSBj Null keys work: https://dotnetfiddle.net/QS7ZNK

viceroypenguin commented 1 year ago

Technically, this matches the behavior of Enumerable.Join. There is no mention of ignoring null in the documentation, but if you test it, you'll notice that nulls are excluded from analysis.

Example:

new int?[] { 1, 2, null, 4, 5, 1, 2, 4, null, null, 3, 6, }
    .Join(
        new int?[] { 2, 3, 4, null, 1, 2, 7, null, 4, 2, 1, },
        x => x,
        x => x,
        (a, b) => (a, b))

A ValueTuple<> (like you did) is the best way to get around it if you have null values that should be matched.

There's room for debate over whether nulls should be: a) silently ignored (as current, and like Join), b) explicitly ignored (via notnull and in docs), or c) handled properly. I can make decent arguments for any of the above, though I lean towards b) for semantic interpretation of null.