public bool Equals(T x, T y) { var type = typeof(T); if (ReferenceEquals(x, y)) { return(true); } // Null? if (!type.IsValueType || (type.IsGenericType && type.GetGenericTypeDefinition().IsAssignableFrom(NullableType))) { if (Object.Equals(x, default(T))) { return(Object.Equals(y, default(T))); } if (Object.Equals(y, default(T))) { return(false); } } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { var tollerance = Tolerance.Empty; return(Numerics.AreEqual(x, y, ref tollerance)); } // Implements IEquatable<T>? var equatable = x as IEquatable <T>; if (equatable != null) { return(equatable.Equals(y)); } // Implements IComparable<T>? var comparableGeneric = x as IComparable <T>; if (comparableGeneric != null) { return(comparableGeneric.CompareTo(y) == 0); } // Implements IComparable? var comparable = x as IComparable; if (comparable != null) { try { return(comparable.CompareTo(y) == 0); } catch (ArgumentException) { // Thrown when two comparable types are not compatible, i.e string and int } } // Enumerable? var enumerableX = x as IEnumerable; var enumerableY = y as IEnumerable; if (enumerableX != null && enumerableY != null) { var enumeratorX = enumerableX.GetEnumerator(); var enumeratorY = enumerableY.GetEnumerator(); var equalityComparer = _innerComparerFactory(); while (true) { bool hasNextX = enumeratorX.MoveNext(); bool hasNextY = enumeratorY.MoveNext(); if (!hasNextX || !hasNextY) { return(hasNextX == hasNextY); } if (!equalityComparer.Equals(enumeratorX.Current, enumeratorY.Current)) { return(false); } } } // Last case, rely on Object.Equals return(Object.Equals(x, y)); }
public bool Equals(T?x, T?y) { if (ReferenceEquals(x, y)) { return(true); } if (x is null || y is null) { return(false); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { var tolerance = Tolerance.Empty; return(Numerics.AreEqual(x, y, ref tolerance)); } // Enumerable? if (x.TryGetEnumerable(out var enumerableX) && y.TryGetEnumerable(out var enumerableY)) { var enumeratorX = enumerableX.GetEnumerator(); var enumeratorY = enumerableY.GetEnumerator(); var equalityComparer = _innerComparerFactory(); while (true) { var hasNextX = enumeratorX.MoveNext(); var hasNextY = enumeratorY.MoveNext(); if (!hasNextX || !hasNextY) { return(hasNextX == hasNextY); } if (!equalityComparer.Equals(enumeratorX.Current, enumeratorY.Current)) { return(false); } } } // Implements IEquatable<T>? if (x is IEquatable <T> equatable) { return(equatable.Equals(y)); } // Implements IComparable<T>? if (x is IComparable <T> comparableGeneric) { return(comparableGeneric.CompareTo(y) == 0); } // Implements IComparable? if (x is IComparable comparable) { try { return(comparable.CompareTo(y) == 0); } catch (ArgumentException) { // Thrown when two comparable types are not compatible, i.e string and int } } // Last case, rely on Object.Equals return(object.Equals(x, y)); }
public void FailsOnIntegralsOutsideOfPercentage(object value) { Assert.IsTrue(Numerics.AreEqual(10000, value, ref tenPercent)); }
public bool AreEqual <T1, T2>(T1 x, T2 y, ref Tolerance tolerance) { Guard.OperationValid(CanCompare(x, y), "Invalid call"); return(Numerics.AreEqual(x, y, ref tolerance)); }
public void CanMatchDecimalWithPercentage() { Assert.IsTrue(Numerics.AreEqual(10000m, 9500m, ref tenPercent)); Assert.IsTrue(Numerics.AreEqual(10000m, 10000m, ref tenPercent)); Assert.IsTrue(Numerics.AreEqual(10000m, 10500m, ref tenPercent)); }
public void CanMatchIntegralsWithPercentage(object value) { Assert.IsTrue(Numerics.AreEqual(10000, value, ref tenPercent)); }
public void CanMatchDecimalWithoutToleranceMode() { Assert.IsTrue(Numerics.AreEqual(123m, 123m, ref zeroTolerance)); }
public void CanMatchWithoutToleranceMode(object value) { Assert.IsTrue(Numerics.AreEqual(value, value, ref zeroTolerance)); }
public void FailsOnDecimalAbovePercentage() { Assert.IsTrue(Numerics.AreEqual(10000m, 11500m, ref tenPercent)); }