Skip to content

Commit

Permalink
Performance improvements in AssertEqualityComparer (conditional IEqua…
Browse files Browse the repository at this point in the history
…table<Y> and IComparable<Y> with type caching)
  • Loading branch information
bradwilson committed Oct 27, 2023
1 parent f184355 commit 6a94a86
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions Sdk/AssertEqualityComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;

Expand All @@ -31,6 +32,8 @@ sealed class AssertEqualityComparer<T> : IEqualityComparer<T>
{
internal static readonly IEqualityComparer DefaultInnerComparer = new AssertEqualityComparerAdapter<object>(new AssertEqualityComparer<object>());

static readonly ConcurrentDictionary<Type, TypeInfo> cacheOfIComparableOfT = new ConcurrentDictionary<Type, TypeInfo>();
static readonly ConcurrentDictionary<Type, TypeInfo> cacheOfIEquatableOfT = new ConcurrentDictionary<Type, TypeInfo>();
readonly Lazy<IEqualityComparer> innerComparer;
static readonly Type typeKeyValuePair = typeof(KeyValuePair<,>);

Expand Down Expand Up @@ -86,12 +89,14 @@ public AssertEqualityComparer(IEqualityComparer innerComparer = null)
if (equatable != null)
return equatable.Equals(y);

// Implements IEquatable<typeof(y)>?
var xType = x.GetType();
var xTypeInfo = xType.GetTypeInfo();
var yType = y.GetType();

var iequatableY = typeof(IEquatable<>).MakeGenericType(yType).GetTypeInfo();
// Implements IEquatable<typeof(y)>?
if (xType != yType)
{
var iequatableY = cacheOfIEquatableOfT.GetOrAdd(yType, (t) => typeof(IEquatable<>).MakeGenericType(t).GetTypeInfo());
if (iequatableY.IsAssignableFrom(xTypeInfo))
{
var equalsMethod = iequatableY.GetDeclaredMethod(nameof(IEquatable<T>.Equals));
Expand All @@ -104,6 +109,7 @@ public AssertEqualityComparer(IEqualityComparer innerComparer = null)
return (bool)equalsMethod.Invoke(x, new object[] { y });
#endif
}
}

// Implements IStructuralEquatable?
var structuralEquatable = x as IStructuralEquatable;
Expand All @@ -127,7 +133,9 @@ public AssertEqualityComparer(IEqualityComparer innerComparer = null)
}

// Implements IComparable<typeof(y)>?
var icomparableY = typeof(IComparable<>).MakeGenericType(yType).GetTypeInfo();
if (xType != yType)
{
var icomparableY = cacheOfIComparableOfT.GetOrAdd(yType, (t) => typeof(IComparable<>).MakeGenericType(t).GetTypeInfo());
if (icomparableY.IsAssignableFrom(xTypeInfo))
{
var compareToMethod = icomparableY.GetDeclaredMethod(nameof(IComparable<T>.CompareTo));
Expand All @@ -149,6 +157,7 @@ public AssertEqualityComparer(IEqualityComparer innerComparer = null)
// If this happens, just swallow up the exception and continue comparing.
}
}
}

// Implements IComparable?
var comparable = x as IComparable;
Expand Down

0 comments on commit 6a94a86

Please sign in to comment.