基元和 IComparable 接口

Primitives and IComparable interface

在 Java 中,如果我想独立于数据类型对任何数据进行排序,我会使用 Comparable 接口,我发现我们在 C# 中有类似的接口,所以我有简单的排序算法:

public static void Sort(IComparable[] arr)
{
    bool swap = true;
    while (swap)
    {
        swap = false;
        for (int i = 0; i < arr.Length - 1; i++)
        {
            if (Less(arr[i + 1], arr[i]))
            {
                Exchange(arr, i, i + 1);
                swap = true;
            }
        }
    }
} 

所以我可以对任何实现 IComparable 接口的对象进行排序,但我不能对任何原始数据类型进行排序,而且据我所知,C# 没有像 int -> Integer 这样的原始数据类型的包装器类型,但是它有一些像 Int32 这样的结构实际上实现了 IComparable 接口,但由于某些原因我仍然不能使用它,例如:

static void Main(string[] args)
{
    Int32[] ints = { 5, 2, 9, 0, 3};
    BubbleSort.Sort(ints);

    ReadKey();
}

我会得到一个错误:

Error   CS1503  Argument 1: cannot convert from 'int[]' to 'System.IComparable[]'

但是如果我们检查 Int32 的元数据,我们可以看到它实现了 IComparable

所以,

  1. 我不知道什么?
  2. 这是怎么回事?
  3. 我怎样才能更好地对任何数据进行排序?

int[] 不是 IComparable[] - 后者是引用数组。

但是有一个简单的解决方案,可以避免装箱。将您的方法声明更改为具有类型参数约束的通用方法:

public static void Sort<T>(IComparable<T>[] arr) where T : IComparable<T>

您可能还需要更改 ExchangeLess 方法 - 您还没有告诉我们那是什么样子的。但它们也可以(而且可能应该)是通用的。 Sort 的方法体此时不需要更改。

如果有人感兴趣:

public static class BubbleSort<T>
{
        public static void Sort(T[] arr, Comparer<T> comparer = null)
        {
            Comparer<T> equaltyComparer = comparer ?? Comparer<T>.Default;

            bool swap = true;
            while (swap)
            {
                swap = false;
                for (int i = 0; i < arr.Length - 1; i++)
                {
                    if (Less(equaltyComparer, arr[i + 1], arr[i]))
                    {
                        Exchange(arr, i, i + 1);
                        swap = true;
                    }
                }
            }
        }
        
        private static bool Less(Comparer<T> comparer, T v, T w)
        {
            return  comparer.Compare(v, w) < 0;
        }

        private static void Exchange(T[] arr, int i, int j)
        {
            T temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
}