-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Handle NaN in value comparers for double/float #22168
Conversation
Note: this does add the NaN check for all databases, including those which don't support it. If we think that's significant we can just have the comparers and leave it to providers to use them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@AndriySvyryd Any Cosmos changes needed here to handle NaN? |
Yes. But I don't think it's high enough of a priority |
In triage we mentioning possibly having core-level floating point mappings with the right comparer, but I see we have no mappings at all in core. I've put the comparers themselves in core, so it's trivial for any non-relational provider to use them if they want, am going to go ahead and merge as-is. |
/// Initializes a new instance of the <see cref="DoubleValueComparer" /> class. | ||
/// </summary> | ||
public DoubleValueComparer() : base( | ||
(x, y) => double.IsNaN(x) ? double.IsNaN(y) : x.Equals(y), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see it's merged now, but
(x, y) => double.IsNaN(x) ? double.IsNaN(y) : x.Equals(y), | |
(x, y) => x.Equals(y), |
will yield the same result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, did not know that... Do you want to submit a cleanup PR for this (and the same for FloatValueComparer)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, will send one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--> #22212
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the value comparer are just doing Equals then do we need a custom value comparer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with @smitpatel. What's the actual issue we're trying to fix here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's what's happening.
- The result of
double.NaN == double.NaN
is false, but the result ofdouble.NaN.Equals(double.NaN)
is true. - Previous to this PR, floating point properties would get a default ValueComparer, whose implementation of Equals is Expression.Equal. That calls the "operator" version which returns false.
- This PR (and DoubleValueComparer / FloatValueComparer cleaned up NaN-handling #22212) fixes that by having a specialized value comparer which calls double.Equals instead of ==, which works correctly.
It may be better to fix this by having a DefaultDoubleValueComparer which is the same as DefaultValueComparer, but calls Equals instead of ==: it's cleaner and would work universally (e.g. Cosmos). @ajcvickers if that makes sense I'll submit that. If we don't do that, we probably want to clean up and remove double/float from DefaultValueComparer as it doesn't work correctly for NaN.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roji Yes, do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixes #22167