Skip to content

Commit

Permalink
Cleanup NaN handling in value comparers (#22242)
Browse files Browse the repository at this point in the history
Follow-up to #22168
  • Loading branch information
roji committed Aug 27, 2020
1 parent a9b0ad7 commit 87d75d4
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 63 deletions.
5 changes: 1 addition & 4 deletions src/EFCore.Relational/Storage/DoubleTypeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ public class DoubleTypeMapping : RelationalTypeMapping
public DoubleTypeMapping(
[NotNull] string storeType,
DbType? dbType = null)
: base(
new RelationalTypeMappingParameters(
new CoreTypeMappingParameters(typeof(double), comparer: new DoubleValueComparer()),
storeType, StoreTypePostfix.None, dbType, unicode: false, size: null, fixedLength: false, precision: null, scale: null))
: base(storeType, typeof(double), dbType)
{
}

Expand Down
5 changes: 1 addition & 4 deletions src/EFCore.Relational/Storage/FloatTypeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ public class FloatTypeMapping : RelationalTypeMapping
public FloatTypeMapping(
[NotNull] string storeType,
DbType? dbType = null)
: base(
new RelationalTypeMappingParameters(
new CoreTypeMappingParameters(typeof(float), comparer: new FloatValueComparer()),
storeType, StoreTypePostfix.None, dbType, unicode: false, size: null, fixedLength: false, precision: null, scale: null))
: base(storeType, typeof(float), dbType)
{
}

Expand Down
25 changes: 0 additions & 25 deletions src/EFCore/ChangeTracking/DoubleValueComparer.cs

This file was deleted.

25 changes: 0 additions & 25 deletions src/EFCore/ChangeTracking/FloatValueComparer.cs

This file was deleted.

46 changes: 43 additions & 3 deletions src/EFCore/ChangeTracking/ValueComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Utilities;
using MethodInfoExtensions = Microsoft.EntityFrameworkCore.Internal.MethodInfoExtensions;

namespace Microsoft.EntityFrameworkCore.ChangeTracking
{
Expand All @@ -28,6 +29,12 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking
/// </summary>
public abstract class ValueComparer : IEqualityComparer
{
private protected static readonly MethodInfo _doubleEqualsMethodInfo
= typeof(double).GetRuntimeMethod(nameof(double.Equals), new[] { typeof(double) });

private protected static readonly MethodInfo _floatEqualsMethodInfo
= typeof(float).GetRuntimeMethod(nameof(float.Equals), new[] { typeof(float) });

internal static readonly MethodInfo ArrayCopyMethod
= typeof(Array).GetMethods()
.Single(
Expand Down Expand Up @@ -197,8 +204,19 @@ public static ValueComparer CreateDefault([NotNull] Type type, bool favorStructu
{
var nonNullabletype = type.UnwrapNullableType();

var comparerType =
nonNullabletype.IsNumeric()
// The equality operator returns false for NaNs, but the Equals methods returns true
if (nonNullabletype == typeof(double))
{
return new DefaultDoubleValueComparer(favorStructuralComparisons);
}

if (nonNullabletype == typeof(float))
{
return new DefaultFloatValueComparer(favorStructuralComparisons);
}

var comparerType = nonNullabletype.IsInteger()
|| nonNullabletype == typeof(decimal)
|| nonNullabletype == typeof(bool)
|| nonNullabletype == typeof(string)
|| nonNullabletype == typeof(DateTime)
Expand All @@ -213,7 +231,7 @@ public static ValueComparer CreateDefault([NotNull] Type type, bool favorStructu
new object[] { favorStructuralComparisons });
}

internal sealed class DefaultValueComparer<T> : ValueComparer<T>
internal class DefaultValueComparer<T> : ValueComparer<T>
{
public DefaultValueComparer(bool favorStructuralComparisons)
: base(favorStructuralComparisons)
Expand All @@ -232,5 +250,27 @@ public override object Snapshot(object instance)
public override T Snapshot(T instance)
=> instance;
}

internal sealed class DefaultDoubleValueComparer : DefaultValueComparer<double>
{
public DefaultDoubleValueComparer(bool favorStructuralComparisons)
: base(favorStructuralComparisons)
{
}

public override Expression ExtractEqualsBody(Expression leftExpression, Expression rightExpression)
=> Expression.Call(leftExpression, _doubleEqualsMethodInfo, rightExpression);
}

internal sealed class DefaultFloatValueComparer : DefaultValueComparer<float>
{
public DefaultFloatValueComparer(bool favorStructuralComparisons)
: base(favorStructuralComparisons)
{
}

public override Expression ExtractEqualsBody(Expression leftExpression, Expression rightExpression)
=> Expression.Call(leftExpression, _floatEqualsMethodInfo, rightExpression);
}
}
}
2 changes: 0 additions & 2 deletions src/EFCore/ChangeTracking/ValueComparer`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ public ValueComparer(bool favorStructuralComparisons)
|| unwrappedType == typeof(Guid)
|| unwrappedType == typeof(bool)
|| unwrappedType == typeof(decimal)
|| unwrappedType == typeof(double)
|| unwrappedType == typeof(float)
|| unwrappedType == typeof(object)
)
{
Expand Down

0 comments on commit 87d75d4

Please sign in to comment.