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);
}
}
}