C#比較類/接口、Dictionary 排序

首先看下List.Sort()方法:

public void Sort(int index, int count, IComparer<T> comparer);  //指定范圍排序
public void Sort(Comparison<T> comparison);
public void Sort();
public void Sort(IComparer<T> comparer);

一.Comparison<T>

public delegate int Comparison<in T>(T x, T y);

概念:表示用于比較相同類型的兩個對象的方法。

  1. 解釋:使用delegate,是為了將方法視為變量并可作為參數(shù)傳遞的實體。
  2. 對Dictionary 排序:
Dictionary<string, int> dic = new Dictionary<string, int>();
dic.Add("index.html", 50);
dic.Add("product.html", 13);
dic.Add("aboutus.html", 4);
dic.Add("online.aspx", 22);
dic.Add("news.aspx", 18);

//第一種
List<KeyValuePair<string, int>> list1 = new List<KeyValuePair<string, int>>(dic);
list1.Sort(h1);

//第二種
List<KeyValuePair<string, int>> list2 = new List<KeyValuePair<string, int>>(dic);
list1.Sort(delegate (KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
{
    return s2.Value.CompareTo(s1.Value);
});

//第三種
List<KeyValuePair<string, int>> list3 = new List<KeyValuePair<string, int>>(dic);
list2.Sort((s1, s2) => { return s1.Value.CompareTo(s2.Value); });

public static int h1(KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
{
    return s2.Value.CompareTo(s1.Value);
}        

二. Comparer<T> ClassIComparer<T>

  1. 概念:為 IComparer<T> 泛型接口實現(xiàn)提供的基類。
public abstract class Comparer<T> : IComparer, IComparer<T>
{
    protected Comparer();
    public static Comparer<T> Default { get; }
    public static Comparer<T> Create(Comparison<T> comparison);
    public abstract int Compare(T x, T y);
}
  1. Comparer<T>和 IComparer<T>的區(qū)別:
  • Comparer<T>是類,并提供了默認比較器,也就是說,如果需要自定義默認比較器,需要自行實現(xiàn)IComparer<T>接口
  • 使用Comparer<T>.Default來獲取默認比較器

三. IComparable<T>

與此實例比較的對象
IComparable<T>,實現(xiàn)接口:IComparer<T> IComparer

public interface IComparable<in T>
{
    int CompareTo(T other);
}

四.Comparer<T> Class、IComparer<T>、IComparable<T>官方案例

class Test
{
    static void Main(string[] args)
    {
        List<Box> Boxes = new List<Box>();
        Boxes.Add(new Box(4, 20, 14));
        Boxes.Add(new Box(12, 12, 12));
        Boxes.Add(new Box(8, 20, 10));
        Boxes.Add(new Box(6, 10, 2));
        Boxes.Add(new Box(2, 8, 4));
        Boxes.Add(new Box(2, 6, 8));
        Boxes.Add(new Box(4, 12, 20));
        Boxes.Add(new Box(18, 10, 4));
        Boxes.Add(new Box(24, 4, 18));
        Boxes.Add(new Box(10, 4, 16));
        Boxes.Add(new Box(10, 2, 10));
        Boxes.Add(new Box(6, 18, 2));
        Boxes.Add(new Box(8, 12, 4));
        Boxes.Add(new Box(12, 10, 8));
        Boxes.Add(new Box(14, 6, 6));
        Boxes.Add(new Box(16, 6, 16));
        Boxes.Add(new Box(2, 8, 12));
        Boxes.Add(new Box(4, 24, 8));
        Boxes.Add(new Box(8, 6, 20));
        Boxes.Add(new Box(18, 18, 12));

        //使用繼承了Comparer<T>的比較器,進行排序。里面覆寫了Compare(T a,T b)方法
        Boxes.Sort(new BoxLengthFirst());  

        foreach (Box bx in Boxes)
        {
            Console.WriteLine("{0}\t{1}\t{2}",
                bx.Height.ToString(), bx.Length.ToString(),
                bx.Width.ToString());
        }

        Console.WriteLine("===============");

        //獲取默認比較器
        Comparer<Box> defComp = Comparer<Box>.Default;  

        // Calling Boxes.Sort() with no parameter
        // is the same as calling Boxs.Sort(defComp)
        // because they are both using the default comparer.
        // 等于調(diào)用Boxs.Sort(defComp);
        Boxes.Sort();

        foreach (Box bx in Boxes)
        {
            //輸出高、長、寬
            Console.WriteLine("{0}\t{1}\t{2}",
                bx.Height.ToString(), bx.Length.ToString(),
                bx.Width.ToString());
        }

        // This explicit interface implementation
        // compares first by the length.
        // Returns -1 because the length of BoxA
        // is less than the length of BoxB.
        BoxLengthFirst LengthFirst = new BoxLengthFirst();

        Comparer<Box> bc = (Comparer<Box>)LengthFirst;

        Box BoxA = new Box(2, 6, 8);
        Box BoxB = new Box(10, 12, 14);
        int x = LengthFirst.Compare(BoxA, BoxB);
        Console.WriteLine();
        Console.WriteLine(x.ToString());
 
        Console.ReadLine();
    }
}
public class BoxLengthFirst : Comparer<Box>
{
    //父類抽象方法 Compare
    // Compares by Length, Height, and Width.
    public override int Compare(Box x, Box y)
    {
        if (x.Length.CompareTo(y.Length) != 0)
        {
            return x.Length.CompareTo(y.Length);
        }
        else if (x.Height.CompareTo(y.Height) != 0)
        {
            return x.Height.CompareTo(y.Height);
        }
        else if (x.Width.CompareTo(y.Width) != 0)
        {
            return x.Width.CompareTo(y.Width);
        }
        else
        {
            return 0;
        }
    }

}


// This class is not demonstrated in the Main method
// and is provided only to show how to implement
// the interface. It is recommended to derive
// from Comparer<T> instead of implementing IComparer<T>.

//沒有在Main方法里演示,推薦使用繼承Comparer<T>的方法。
public class BoxComp : IComparer<Box>
{
    // Compares by Height, Length, and Width.
    public int Compare(Box x, Box y)
    {
        if (x.Height.CompareTo(y.Height) != 0)
        {
            return x.Height.CompareTo(y.Height);
        }
        else if (x.Length.CompareTo(y.Length) != 0)
        {
            return x.Length.CompareTo(y.Length);
        }
        else if (x.Width.CompareTo(y.Width) != 0)
        {
            return x.Width.CompareTo(y.Width);
        }
        else
        {
            return 0;
        }
    }
}

public class Box : IComparable<Box>
{
    public Box(int h, int l, int w)
    {
        this.Height = h;
        this.Length = l;
        this.Width = w;
    }
    public int Height { get; private set; }
    public int Length { get; private set; }
    public int Width { get; private set; }

    public int CompareTo(Box other)
    {
        // Compares Height, Length, and Width.
        if (this.Height.CompareTo(other.Height) != 0)
        {
            return this.Height.CompareTo(other.Height);
        }
        else if (this.Length.CompareTo(other.Length) != 0)
        {
            return this.Length.CompareTo(other.Length);
        }
        else if (this.Width.CompareTo(other.Width) != 0)
        {
            return this.Width.CompareTo(other.Width);
        }
        else
        {
            return 0;
        }
    }
}

五. Comparison<T>、 Comparer<T>、 System.IComparable、IComparable<T>的區(qū)別

  1. Comparison<T>,繼承委托。開發(fā)人員可以在外部寫個用于比較大小的函數(shù),然后作為 Comparison<T>類型的參數(shù)傳入,進行比較,非常方便。

  2. 派生自 Comparer<T> 類和實現(xiàn) System.IComparable 接口之間的差異如下:

  • 若要指定默認情況下(Default獲取)應(yīng)如何比較兩個對象,請在類中實現(xiàn) System.IComparable 接口。 這可確保排序操作將使用您提供的默認比較代碼。

  • 若要定義要使用的比較器而不是默認比較器,請從 Comparer<T> 類派生。 然后,您可以在采用比較器作為參數(shù)的排序操作中使用此比較器。

  1. Default 屬性返回的對象使用 System.IComparable<T> 泛型接口來比較兩個對象。 如果類型 T 未實現(xiàn) System.IComparable<T> 泛型接口,Default 屬性返回使用 System.IComparable 接口的 Comparer<T>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。