public int Compare(T x, T y)
        {
            var enumerableComparer = new EnumerableComparer();

            if (enumerableComparer.CanCompare(x, y))
            {
                return(enumerableComparer.Compare((IEnumerable)x, (IEnumerable)y));
            }

            var nullComparer = new NullComparer();

            if (nullComparer.CanCompare(x, y))
            {
                return(nullComparer.Compare(x, y));
            }

            // Same type?
            if (x.GetType() != y.GetType())
            {
                return(-1);
            }

            // Implements IComparable<T>?
            IComparable <T> comparable1 = x as IComparable <T>;

            if (comparable1 != null)
            {
                return(comparable1.CompareTo(y));
            }

            // Implements IComparable?
            IComparable comparable2 = x as IComparable;

            if (comparable2 != null)
            {
                return(comparable2.CompareTo(y));
            }

            // Implements IEquatable<T>?
            IEquatable <T> equatable = x as IEquatable <T>;

            if (equatable != null)
            {
                return(equatable.Equals(y) ? 0 : -1);
            }

            // Last case, rely on Object.Equals
            return(object.Equals(x, y) ? 0 : -1);
        }