public int Compare(T x, T y) { if (_comparer != null) { return(_comparer.Compare(x, y)); } if (typeof(T) == typeof(DateTime)) { var x1 = (DateTime)(object)(x); var y1 = (DateTime)(object)(y); return(x1.CompareTo(y1)); } if (typeof(T) == typeof(long)) { var x1 = (long)(object)(x); var y1 = (long)(object)(y); return(x1.CompareTo(y1)); } if (typeof(T) == typeof(ulong)) { var x1 = (ulong)(object)(x); var y1 = (ulong)(object)(y); return(x1.CompareTo(y1)); } if (typeof(T) == typeof(int)) { var x1 = (int)(object)(x); var y1 = (int)(object)(y); return(x1.CompareTo(y1)); } if (typeof(T) == typeof(uint)) { var x1 = (uint)(object)(x); var y1 = (uint)(object)(y); return(x1.CompareTo(y1)); } // NB all primitive types are IComparable, all custom types could be easily made such // This optimization using Spreads.Unsafe package works for any type that implements // the interface and is as fast as `typeof(T) == typeof(...)` approach. // The special cases above are left for scenarios when the "static readonly" optimization // doesn't work, e.g. AOT. See discussion #100. if (IsIComparable) { return(Unsafe.CompareToConstrained(ref x, ref y)); } return(CompareSlow(x, y)); }
public void ComparerInterfaceAndCachedConstrainedComparer() { var c = Comparer <long> .Default; IComparer <long> ic = Comparer <long> .Default; var cc = KeyComparer <long> .Default; const int count = 100000000; for (int r = 0; r < 10; r++) { var sum = 0L; using (Benchmark.Run("Default", count)) { for (int i = 0; i < count; i++) { sum += c.Compare(i, i - 1); } } Assert.True(sum > 0); sum = 0L; using (Benchmark.Run("Interface", count)) { for (int i = 0; i < count; i++) { sum += ic.Compare(i, i - 1); } } Assert.True(sum > 0); sum = 0L; using (Benchmark.Run("KeyComparer", count)) { for (int i = 0; i < count; i++) { sum += cc.Compare(i, i - 1); } } Assert.True(sum > 0); sum = 0L; using (Benchmark.Run("Unsafe", count)) { for (int i = 0; i < count; i++) { var other = i - 1; sum += Unsafe.CompareToConstrained(ref i, ref other); } } } Benchmark.Dump(); }
public void CouldUseCompareAndEqualsMethods() { var v1 = new CompEq(1); var v2 = new CompEq(2); var v3 = new CompEq(2); Assert.AreEqual(-1, Unsafe.CompareToConstrained(ref v1, ref v2)); Assert.AreEqual(1, Unsafe.CompareToConstrained(ref v2, ref v1)); Assert.AreEqual(0, Unsafe.CompareToConstrained(ref v2, ref v3)); Assert.AreEqual(1, Unsafe.CompareToConstrained(ref v3, ref v1)); Assert.True(Unsafe.EqualsConstrained(ref v2, ref v3)); Assert.False(Unsafe.EqualsConstrained(ref v1, ref v3)); }