/// <summary> /// Test whether the constraint is satisfied by a given value /// </summary> /// <param name="actual">The value to be tested</param> /// <returns>True for success, false for failure</returns> public override bool Matches(object actual) { this.actual = actual; int icomp = Numerics.Compare(expected, actual); return(icomp < 0 && gtOK || icomp == 0 && eqOK || icomp > 0 && ltOK); }
public void CanCompareDecimalAndHighDouble() { var expected = Convert.ToDouble(decimal.MaxValue) * 1.1; var actual = decimal.MaxValue; var result = Numerics.Difference(expected, actual, ToleranceMode.Linear); Assert.That(result, Is.EqualTo(7.9228162514264408E+27)); }
private bool ObjectsEqual(object expected, object actual) { if (expected == null && actual == null) { return(true); } if (expected == null || actual == null) { return(false); } Type expectedType = expected.GetType(); Type actualType = actual.GetType(); if (expectedType.IsArray && actualType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)expected, (Array)actual)); } if (expected is ICollection && actual is ICollection) { return(CollectionsEqual((ICollection)expected, (ICollection)actual)); } if (expected is Stream && actual is Stream) { return(StreamsEqual((Stream)expected, (Stream)actual)); } if (compareWith != null) { return(compareWith.Compare(expected, actual) == 0); } if (Numerics.IsNumericType(expected) && Numerics.IsNumericType(actual)) { return(Numerics.AreEqual(expected, actual, tolerance)); } if (expected is string && actual is string) { return(string.Compare((string)expected, (string)actual, caseInsensitive) == 0); } foreach (Type type in constraintHelpers.Keys) { if (type.IsInstanceOfType(expected) && type.IsInstanceOfType(actual)) { Type constraintType = (Type)constraintHelpers[type]; Constraint constraint = (Constraint)NUnitLite.Reflect.Construct(constraintType, expected); return(constraint.Matches(actual)); } } return(expected.Equals(actual)); }
public void CanCalculateDifferenceDecimalsWithHighPrecision() { var expected = 95217168582.206969750145956m; var actual = 95217168582.20696975014595521m; var result = Numerics.Difference(expected, actual, ToleranceMode.Linear); Assert.That(result, Is.EqualTo(0.00000000000000079M)); }
public void CanCompareDecimalsWithHighPrecision() { var expected = 95217168582.206969750145956m; var actual = 95217168582.20696975014595521m; var result = Numerics.Compare(expected, actual); Assert.That(expected, Is.GreaterThan(actual)); }
public void CanCompareMidRangeDecimalAndDouble() { var expected = 3.14159m; var actual = 2.718281d; var result = Numerics.Difference(expected, actual, ToleranceMode.Linear); Assert.That(result, Is.EqualTo(0.423309)); }
private bool ObjectsEqual(object expected, object actual) { if (expected == null && actual == null) { return(true); } if (expected == null || actual == null) { return(false); } Type expectedType = expected.GetType(); Type actualType = actual.GetType(); if (expectedType.IsArray && actualType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)expected, (Array)actual)); } if (expected is ICollection && actual is ICollection) { return(CollectionsEqual((ICollection)expected, (ICollection)actual)); } if (expected is Stream && actual is Stream) { return(StreamsEqual((Stream)expected, (Stream)actual)); } if (compareWith != null) { return(compareWith.Compare(expected, actual) == 0); } if (expected is DirectoryInfo && actual is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)expected, (DirectoryInfo)actual)); } if (Numerics.IsNumericType(expected) && Numerics.IsNumericType(actual)) { return(Numerics.AreEqual(expected, actual, ref tolerance)); } if (expected is string && actual is string) { return(StringsEqual((string)expected, (string)actual)); } if (expected is DateTime && actual is DateTime && tolerance is TimeSpan) { return(((DateTime)expected - (DateTime)actual).Duration() <= (TimeSpan)tolerance); } return(expected.Equals(actual)); }
private void CheckLinearAndNumeric() { if (mode != ToleranceMode.Linear) { throw new InvalidOperationException((mode == ToleranceMode.None) ? "Tolerance amount must be specified before setting mode" : "Tried to use multiple tolerance modes at the same time"); } if (!Numerics.IsNumericType(amount)) { throw new InvalidOperationException("A numeric tolerance is required"); } }
private Range PercentRange(object value) { if (!Numerics.IsNumericType(Amount) || !Numerics.IsNumericType(value)) { throw new InvalidOperationException("Cannot create range for a non-numeric value"); } var v = Convert.ToDouble(value); var offset = v * Convert.ToDouble(Amount) / 100.0; return(new Range(v - offset, v + offset)); }
private Range LinearRange(object value) { if (Amount is double || value is double) { var amount = Convert.ToDouble(Amount); var v = Convert.ToDouble(value); return(new Range(v - amount, v + amount)); } if (Amount is float || value is float) { var amount = Convert.ToSingle(Amount); var v = Convert.ToSingle(value); return(new Range(v - amount, v + amount)); } if (Amount is decimal || value is decimal) { var amount = Convert.ToDecimal(Amount); var v = Convert.ToDecimal(value); return(new Range(v - amount, v + amount)); } if (Amount is ulong || value is ulong) { var amount = Convert.ToUInt64(Amount); var v = Convert.ToUInt64(value); return(new Range(v - amount, v + amount)); } if (Amount is long || value is long) { var amount = Convert.ToInt64(Amount); var v = Convert.ToInt64(value); return(new Range(v - amount, v + amount)); } if (Amount is uint || value is uint) { var amount = Convert.ToUInt32(Amount); var v = Convert.ToUInt32(value); return(new Range(v - amount, v + amount)); } if (Numerics.IsFixedPointNumeric(Amount) && Numerics.IsFixedPointNumeric(value)) { var amount = Convert.ToInt32(Amount); var v = Convert.ToInt32(value); return(new Range(v - amount, v + amount)); } throw new InvalidOperationException("Cannot create range for a non-numeric value"); }
/// <summary> /// Compares two objects /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public int Compare(object x, object y) { if (x == null) { return(y == null ? 0 : -1); } else if (y == null) { return(+1); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.Compare(x, y)); } Type xType = x.GetType(); Type yType = y.GetType(); // If we use BindingFlags.ExactBinding it will prevent us finding CompareTo(object) // It however also prevents finding CompareTo(TBase) when called with TDerived // Nor will it find CompareTo(int) when called with a short. // We fallback to explicitly exclude CompareTo(object) bool IsIComparable(MethodInfo method) => method.GetParameters()[0].ParameterType == typeof(object); MethodInfo method = xType.GetMethod("CompareTo", new Type[] { yType }); if (method != null && !IsIComparable(method)) { return((int)method.Invoke(x, new object[] { y })); } method = yType.GetMethod("CompareTo", new Type[] { xType }); if (method != null && !IsIComparable(method)) { return(-(int)method.Invoke(y, new object[] { x })); } if (x is IComparable) { return(((IComparable)x).CompareTo(y)); } if (y is IComparable) { return(-((IComparable)y).CompareTo(x)); } throw new ArgumentException("Neither value implements IComparable or IComparable<T>"); }
/// <summary> /// Tests that the current Tolerance is linear with a /// numeric value, throwing an exception if it is not. /// </summary> private void CheckLinearAndNumeric() { if (Mode != ToleranceMode.Linear) { throw new InvalidOperationException(Mode == ToleranceMode.Unset ? ModeMustFollowTolerance : MultipleToleranceModes); } if (!Numerics.IsNumericType(Amount)) { throw new InvalidOperationException(NumericToleranceRequired); } }
/// <summary> /// Compares two objects /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public int Compare(object x, object y) { if (x == null) { return(y == null ? 0 : -1); } else if (y == null) { return(+1); } if (x is char && y is char) { return((char)x == (char)y ? 0 : 1); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.Compare(x, y)); } if (x is IComparable) { return(((IComparable)x).CompareTo(y)); } if (y is IComparable) { return(-((IComparable)y).CompareTo(x)); } Type xType = x.GetType(); Type yType = y.GetType(); MethodInfo method = xType.GetMethod("CompareTo", new Type[] { yType }); if (method != null) { return((int)method.Invoke(x, new object[] { y })); } method = yType.GetMethod("CompareTo", new Type[] { xType }); if (method != null) { return(-(int)method.Invoke(y, new object[] { x })); } throw new ArgumentException("Neither value implements IComparable or IComparable<T>"); }
public int Compare(object x, object y) { if (x == null) { return((y != null) ? (-1) : 0); } if (y == null) { return(1); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.Compare(x, y)); } if (x is IComparable) { return(((IComparable)x).CompareTo(y)); } if (y is IComparable) { return(-((IComparable)y).CompareTo(x)); } Type type = x.GetType(); Type type2 = y.GetType(); MethodInfo method = type.GetMethod("CompareTo", new Type[1] { type2 }); if (method != null) { return((int)method.Invoke(x, new object[1] { y })); } method = type2.GetMethod("CompareTo", new Type[1] { type }); if (method != null) { return(-(int)method.Invoke(y, new object[1] { x })); } throw new ArgumentException("Neither value implements IComparable or IComparable<T>"); }
/// <summary> /// Compares two objects /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public int Compare(object x, object y) { if (x == null) { return(y == null ? 0 : -1); } else if (y == null) { return(+1); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.Compare(x, y)); } Type xType = x.GetType(); Type yType = y.GetType();
private static bool IsSpecialComparisonType(Type type) { if (type.IsGenericType) { return(type.FullName.StartsWith("System.Collections.Generic.KeyValuePair`2", StringComparison.Ordinal)); } else if (Numerics.IsNumericType(type)) { return(true); } else { return (type == typeof(string) || type == typeof(char) || type == typeof(DateTimeOffset) || type == typeof(DictionaryEntry)); } }
public void FailsOnDecimalAbovePercentage() { Assert.Throws <AssertionException>(() => Assert.IsTrue(Numerics.AreEqual(10000m, 11500m, ref tenPercent))); }
public void FailsOnIntegralsOutsideOfPercentage(object value) { Assert.Throws <AssertionException>(() => Assert.IsTrue(Numerics.AreEqual(10000, value, ref tenPercent))); }
public void DifferenceForNonNumericTypesReturnsNaN() { Assert.That(Numerics.Difference(new object(), new object(), tenPercent.Mode), Is.EqualTo(double.NaN)); }
public void CanCalculatePercentDifference() { Assert.That(Numerics.Difference(10000m, 8500m, tenPercent.Mode), Is.EqualTo(15)); Assert.That(Numerics.Difference(10000m, 11500m, tenPercent.Mode), Is.EqualTo(-15)); }
public void CanCalculateAbsoluteDifference() { Assert.That(Numerics.Difference(10000m, 9500m, absoluteTolerance.Mode), Is.EqualTo(500m)); Assert.That(Convert.ToDouble(Numerics.Difference(0.1, 0.05, absoluteTolerance.Mode)), Is.EqualTo(0.05).Within(0.00001)); Assert.That(Convert.ToDouble(Numerics.Difference(0.1, 0.15, absoluteTolerance.Mode)), Is.EqualTo(-0.05).Within(0.00001)); }
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)); }
/// <summary> /// Compares two objects for equality. /// </summary> public bool ObjectsEqual(object x, object y) { this.failurePoints = new List <object>(); if (x == null && y == null) { return(true); } if (x == null || y == null) { return(false); } Type xType = x.GetType(); Type yType = y.GetType(); if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)x, (Array)y)); } if (x is ICollection && y is ICollection) { return(CollectionsEqual((ICollection)x, (ICollection)y)); } if (x is IEnumerable && y is IEnumerable && !(x is string && y is string)) { return(EnumerablesEqual((IEnumerable)x, (IEnumerable)y)); } if (externalComparer != null) { return(externalComparer.ObjectsEqual(x, y)); } if (x is string && y is string) { return(StringsEqual((string)x, (string)y)); } if (x is Stream && y is Stream) { return(StreamsEqual((Stream)x, (Stream)y)); } if (x is DirectoryInfo && y is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)x, (DirectoryInfo)y)); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.AreEqual(x, y, ref tolerance)); } if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (x is DateTime && y is DateTime) { return(((DateTime)x - (DateTime)y).Duration() <= amount); } if (x is TimeSpan && y is TimeSpan) { return(((TimeSpan)x - (TimeSpan)y).Duration() <= amount); } } return(x.Equals(y)); }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { this.failurePoints = new List <FailurePoint>(); if (x == null && y == null) { return(true); } if (x == null || y == null) { return(false); } if (object.ReferenceEquals(x, y)) { return(true); } Type xType = x.GetType(); Type yType = y.GetType(); Type xGenericTypeDefinition = xType.IsGenericType ? xType.GetGenericTypeDefinition() : null; Type yGenericTypeDefinition = yType.IsGenericType ? yType.GetGenericTypeDefinition() : null; EqualityAdapter externalComparer = GetExternalComparer(x, y); if (externalComparer != null) { return(externalComparer.AreEqual(x, y)); } if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)x, (Array)y, ref tolerance)); } if (x is IDictionary && y is IDictionary) { return(DictionariesEqual((IDictionary)x, (IDictionary)y, ref tolerance)); } // Issue #70 - EquivalentTo isn't compatible with IgnoreCase for dictionaries if (x is DictionaryEntry && y is DictionaryEntry) { return(DictionaryEntriesEqual((DictionaryEntry)x, (DictionaryEntry)y, ref tolerance)); } // IDictionary<,> will eventually try to compare it's key value pairs when using CollectionTally if (xGenericTypeDefinition == typeof(KeyValuePair <,>) && yGenericTypeDefinition == typeof(KeyValuePair <,>)) { var keyTolerance = Tolerance.Exact; object xKey = xType.GetProperty("Key").GetValue(x, null); object yKey = yType.GetProperty("Key").GetValue(y, null); object xValue = xType.GetProperty("Value").GetValue(x, null); object yValue = yType.GetProperty("Value").GetValue(y, null); return(AreEqual(xKey, yKey, ref keyTolerance) && AreEqual(xValue, yValue, ref tolerance)); } //if (x is ICollection && y is ICollection) // return CollectionsEqual((ICollection)x, (ICollection)y, ref tolerance); if (x is string && y is string) { return(StringsEqual((string)x, (string)y)); } if (x is IEnumerable && y is IEnumerable) { return(EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance)); } if (x is Stream && y is Stream) { return(StreamsEqual((Stream)x, (Stream)y)); } if (x is char && y is char) { return(CharsEqual((char)x, (char)y)); } #if !PORTABLE if (x is DirectoryInfo && y is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)x, (DirectoryInfo)y)); } #endif if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.AreEqual(x, y, ref tolerance)); } #if !NETCF if (x is DateTimeOffset && y is DateTimeOffset) { bool result; DateTimeOffset xAsOffset = (DateTimeOffset)x; DateTimeOffset yAsOffset = (DateTimeOffset)y; if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; result = (xAsOffset - yAsOffset).Duration() <= amount; } else { result = xAsOffset == yAsOffset; } if (result && WithSameOffset) { result = xAsOffset.Offset == yAsOffset.Offset; } return(result); } #endif if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (x is DateTime && y is DateTime) { return(((DateTime)x - (DateTime)y).Duration() <= amount); } if (x is TimeSpan && y is TimeSpan) { return(((TimeSpan)x - (TimeSpan)y).Duration() <= amount); } } if (FirstImplementsIEquatableOfSecond(xType, yType)) { return(InvokeFirstIEquatableEqualsSecond(x, y)); } else if (xType != yType && FirstImplementsIEquatableOfSecond(yType, xType)) { return(InvokeFirstIEquatableEqualsSecond(y, x)); } return(x.Equals(y)); }
public bool AreEqual(object x, object y, ref Tolerance tolerance) { failurePoints = new ObjectList(); if (x == null && y == null) { return(true); } if (x == null || y == null) { return(false); } if (object.ReferenceEquals(x, y)) { return(true); } Type type = x.GetType(); Type type2 = y.GetType(); EqualityAdapter externalComparer = GetExternalComparer(x, y); if (externalComparer != null) { return(externalComparer.AreEqual(x, y)); } if (type.IsArray && type2.IsArray && !compareAsCollection) { return(ArraysEqual((Array)x, (Array)y, ref tolerance)); } if (x is IDictionary && y is IDictionary) { return(DictionariesEqual((IDictionary)x, (IDictionary)y, ref tolerance)); } if (x is IEnumerable && y is IEnumerable && (!(x is string) || !(y is string))) { return(EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance)); } if (x is string && y is string) { return(StringsEqual((string)x, (string)y)); } if (x is Stream && y is Stream) { return(StreamsEqual((Stream)x, (Stream)y)); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.AreEqual(x, y, ref tolerance)); } if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan timeSpan = (TimeSpan)tolerance.Value; if (x is DateTime && y is DateTime) { return(((DateTime)x - (DateTime)y).Duration() <= timeSpan); } if (x is TimeSpan && y is TimeSpan) { return(((TimeSpan)x - (TimeSpan)y).Duration() <= timeSpan); } } return(x.Equals(y)); }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { this.failurePoints = new ArrayList(); if (x == null && y == null) { return(true); } if (x == null || y == null) { return(false); } if (object.ReferenceEquals(x, y)) { return(true); } Type xType = x.GetType(); Type yType = y.GetType(); EqualityAdapter externalComparer = GetExternalComparer(x, y); if (externalComparer != null) { return(externalComparer.AreEqual(x, y)); } if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)x, (Array)y, ref tolerance)); } if (x is IDictionary && y is IDictionary) { return(DictionariesEqual((IDictionary)x, (IDictionary)y, ref tolerance)); } //if (x is ICollection && y is ICollection) // return CollectionsEqual((ICollection)x, (ICollection)y, ref tolerance); if (x is IEnumerable && y is IEnumerable && !(x is string && y is string)) { return(EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance)); } if (x is string && y is string) { return(StringsEqual((string)x, (string)y)); } if (x is Stream && y is Stream) { return(StreamsEqual((Stream)x, (Stream)y)); } if (x is DirectoryInfo && y is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)x, (DirectoryInfo)y)); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.AreEqual(x, y, ref tolerance)); } if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (x is DateTime && y is DateTime) { return(((DateTime)x - (DateTime)y).Duration() <= amount); } if (x is TimeSpan && y is TimeSpan) { return(((TimeSpan)x - (TimeSpan)y).Duration() <= amount); } } #if CLR_2_0 || CLR_4_0 if (FirstImplementsIEquatableOfSecond(xType, yType)) { return(InvokeFirstIEquatableEqualsSecond(x, y)); } else if (FirstImplementsIEquatableOfSecond(yType, xType)) { return(InvokeFirstIEquatableEqualsSecond(y, x)); } #endif return(x.Equals(y)); }
private bool ObjectsEqual(object expected, object actual, ref Tolerance tolerance) { if (expected == null && actual == null) { return(true); } if (expected == null || actual == null) { return(false); } if (object.ReferenceEquals(expected, actual)) { return(true); } Type xType = expected.GetType(); Type yType = actual.GetType(); EqualityAdapter externalComparer = GetExternalComparer(expected, actual); if (externalComparer != null) { return(externalComparer.AreEqual(expected, actual)); } if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)expected, (Array)actual, ref tolerance)); } if (expected is IDictionary && actual is IDictionary) { return(DictionariesEqual((IDictionary)expected, (IDictionary)actual, ref tolerance)); } // Issue #70 - EquivalentTo isn't compatible with IgnoreCase for dictionaries if (expected is DictionaryEntry && actual is DictionaryEntry) { return(DictionaryEntriesEqual((DictionaryEntry)expected, (DictionaryEntry)actual, ref tolerance)); } #if CLR_2_0 || CLR_4_0 // IDictionary<,> will eventually try to compare it's key value pairs when using CollectionTally if (xType.IsGenericType && xType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>) && yType.IsGenericType && yType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)) { Tolerance keyTolerance = new Tolerance(0); object xKey = xType.GetProperty("Key").GetValue(expected, null); object yKey = yType.GetProperty("Key").GetValue(actual, null); object xValue = xType.GetProperty("Value").GetValue(expected, null); object yValue = yType.GetProperty("Value").GetValue(actual, null); return(AreEqual(xKey, yKey, ref keyTolerance) && AreEqual(xValue, yValue, ref tolerance)); } #endif if (expected is IEnumerable && actual is IEnumerable && !(expected is string && actual is string)) { return(EnumerablesEqual((IEnumerable)expected, (IEnumerable)actual, ref tolerance)); } if (expected is string && actual is string) { return(StringsEqual((string)expected, (string)actual)); } if (expected is Stream && actual is Stream) { return(StreamsEqual((Stream)expected, (Stream)actual)); } if (expected is char && actual is char) { return(CharsEqual((char)expected, (char)actual)); } if (expected is DirectoryInfo && actual is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)expected, (DirectoryInfo)actual)); } if (Numerics.IsNumericType(expected) && Numerics.IsNumericType(actual)) { return(Numerics.AreEqual(expected, actual, ref tolerance)); } if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (expected is DateTime && actual is DateTime) { return(((DateTime)expected - (DateTime)actual).Duration() <= amount); } #if CLR_2_0 || CLR_4_0 if (expected is DateTimeOffset && actual is DateTimeOffset) { return(((DateTimeOffset)expected - (DateTimeOffset)actual).Duration() <= amount); } #endif if (expected is TimeSpan && actual is TimeSpan) { return(((TimeSpan)expected - (TimeSpan)actual).Duration() <= amount); } } #if CLR_2_0 || CLR_4_0 if (FirstImplementsIEquatableOfSecond(xType, yType)) { return(InvokeFirstIEquatableEqualsSecond(expected, actual)); } else if (FirstImplementsIEquatableOfSecond(yType, xType)) { return(InvokeFirstIEquatableEqualsSecond(actual, expected)); } #endif return(expected.Equals(actual)); }