<PackageReference Include="NUnit" Version="4.1.0" />

EqualityAdapter

public abstract class EqualityAdapter
EqualityAdapter class handles all equality comparisons that use an IEqualityComparer, IEqualityComparer<T> or a ComparisonAdapter.
using NUnit.Framework.Internal; using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace NUnit.Framework.Constraints { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public abstract class EqualityAdapter { [System.Runtime.CompilerServices.Nullable(0)] private class ComparerAdapter : EqualityAdapter { private readonly IComparer _comparer; public ComparerAdapter(IComparer comparer) { _comparer = comparer; } public override bool AreEqual(object x, object y) { return _comparer.Compare(x, y) == 0; } } [System.Runtime.CompilerServices.Nullable(0)] private class EqualityComparerAdapter : EqualityAdapter { private readonly IEqualityComparer _comparer; public EqualityComparerAdapter(IEqualityComparer comparer) { _comparer = comparer; } public override bool AreEqual(object x, object y) { return _comparer.Equals(x, y); } } [System.Runtime.CompilerServices.Nullable(0)] internal sealed class PredicateEqualityAdapter<[System.Runtime.CompilerServices.Nullable(2)] TActual, [System.Runtime.CompilerServices.Nullable(2)] TExpected> : EqualityAdapter { private readonly Func<TActual, TExpected, bool> _comparison; public override bool CanCompare(object x, object y) { if (TypeHelper.CanCast<TExpected>(x)) return TypeHelper.CanCast<TActual>(y); return false; } public override bool AreEqual(object x, object y) { return _comparison((TActual)y, (TExpected)x); } public PredicateEqualityAdapter(Func<TActual, TExpected, bool> comparison) { _comparison = comparison; } } [System.Runtime.CompilerServices.Nullable(0)] private abstract class GenericEqualityAdapter<[System.Runtime.CompilerServices.Nullable(2)] T> : EqualityAdapter { public override bool CanCompare(object x, object y) { if (TypeHelper.CanCast<T>(x)) return TypeHelper.CanCast<T>(y); return false; } protected void CastOrThrow([System.Runtime.CompilerServices.Nullable(2)] object x, [System.Runtime.CompilerServices.Nullable(2)] object y, out T xValue, out T yValue) { if (!TypeHelper.TryCast<T>(x, out T value)) throw new ArgumentException("Cannot compare " + (x?.ToString() ?? "null")); if (!TypeHelper.TryCast<T>(y, out T value2)) throw new ArgumentException("Cannot compare " + (y?.ToString() ?? "null")); xValue = value; yValue = value2; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] private class EqualityComparerAdapter<[System.Runtime.CompilerServices.Nullable(2)] T> : GenericEqualityAdapter<T> { private readonly IEqualityComparer<T> _comparer; public EqualityComparerAdapter(IEqualityComparer<T> comparer) { _comparer = comparer; } public override bool AreEqual(object x, object y) { CastOrThrow(x, y, out T xValue, out T yValue); return _comparer.Equals(xValue, yValue); } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] private class ComparerAdapter<[System.Runtime.CompilerServices.Nullable(2)] T> : GenericEqualityAdapter<T> { private readonly IComparer<T> _comparer; public ComparerAdapter(IComparer<T> comparer) { _comparer = comparer; } public override bool AreEqual(object x, object y) { CastOrThrow(x, y, out T xValue, out T yValue); return _comparer.Compare(xValue, yValue) == 0; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] private class ComparisonAdapter<[System.Runtime.CompilerServices.Nullable(2)] T> : GenericEqualityAdapter<T> { private readonly Comparison<T> _comparer; public ComparisonAdapter(Comparison<T> comparer) { _comparer = comparer; } public override bool AreEqual(object x, object y) { CastOrThrow(x, y, out T xValue, out T yValue); return _comparer(xValue, yValue) == 0; } } public abstract bool AreEqual(object x, object y); public virtual bool AreEqual(object x, object y, ref Tolerance tolerance) { if (!tolerance.HasVariance) return AreEqual(x, y); throw new InvalidOperationException("Tolerance is not supported for this comparison"); } public virtual bool CanCompare(object x, object y) { if (x is string || !(x is IEnumerable)) { if (!(y is string)) return !(y is IEnumerable); return true; } return false; } public static EqualityAdapter For(IComparer comparer) { return new ComparerAdapter(comparer); } public static EqualityAdapter For(IEqualityComparer comparer) { return new EqualityComparerAdapter(comparer); } public static EqualityAdapter For<[System.Runtime.CompilerServices.Nullable(2)] TExpected, [System.Runtime.CompilerServices.Nullable(2)] TActual>(Func<TExpected, TActual, bool> comparison) { return new PredicateEqualityAdapter<TExpected, TActual>(comparison); } public static EqualityAdapter For<[System.Runtime.CompilerServices.Nullable(2)] T>(IEqualityComparer<T> comparer) { return new EqualityComparerAdapter<T>(comparer); } public static EqualityAdapter For<[System.Runtime.CompilerServices.Nullable(2)] T>(IComparer<T> comparer) { return new ComparerAdapter<T>(comparer); } public static EqualityAdapter For<[System.Runtime.CompilerServices.Nullable(2)] T>(Comparison<T> comparer) { return new ComparisonAdapter<T>(comparer); } } }