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


 
         

作者:l625208058

 
         

鏈接:https://www.jianshu.com/p/cd1be6652570



先 F12 看下 List.Sort() 方法:
1 public void Sort(int index, int count, IComparer<T> comparer);  //指定范圍排序
2 public void Sort(Comparison<T> comparison); //Comparison<T>其實就是個委托
3 public void Sort(); //使用默認排序
4 public void Sort(IComparer<T> comparer); //使用一個自定義排序者

 

一. Comparison<T>

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

這其實就是個委托,排序示例:

 1 Dictionary<string, int> dic = new Dictionary<string, int>();
 2 dic.Add("index.html", 50);
 3 dic.Add("product.html", 13);
 4 dic.Add("aboutus.html", 4);
 5 dic.Add("online.aspx", 22);
 6 dic.Add("news.aspx", 18);
 7 
 8 public static int h1(KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
 9 {
10     return s2.Value.CompareTo(s1.Value);
11 }        
12 
13 //第一種,使用預先定義的靜態方法
14 List<KeyValuePair<string, int>> list1 = new List<KeyValuePair<string, int>>(dic);
15 list1.Sort(h1);
16 
17 //第二種,使用Dictionary<string, int> dic = new Dictionary<string, int>();
18 dic.Add("index.html", 50);
19 dic.Add("product.html", 13);
20 dic.Add("aboutus.html", 4);
21 dic.Add("online.aspx", 22);
22 dic.Add("news.aspx", 18);
23 
24 public static int h1(KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
25 {
26     return s2.Value.CompareTo(s1.Value);
27 }        
28 
29 //第一種,使用預先定義的靜態方法
30 List<KeyValuePair<string, int>> list1 = new List<KeyValuePair<string, int>>(dic);
31 list1.Sort(h1);
32 
33 //第二種,使用匿名方法
34 List<KeyValuePair<string, int>> list2 = new List<KeyValuePair<string, int>>(dic);
35 list1.Sort(delegate (KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
36 {
37     return s2.Value.CompareTo(s1.Value);
38 });
39 
40 //第三種,使用 lambda 表達式
41 List<KeyValuePair<string, int>> list3 = new List<KeyValuePair<string, int>>(dic);
42 list2.Sort((s1, s2) => { return s1.Value.CompareTo(s2.Value); });

二. Comparer<T>IComparer<T>

  1. 概念:為 IComparer<T> 泛型接口實現提供的基類。

1 public abstract class Comparer<T> : IComparer, IComparer<T>
2 {
3     protected Comparer();
4     public static Comparer<T> Default { get; }
5     public static Comparer<T> Create(Comparison<T> comparison);
6     public abstract int Compare(T x, T y);
7 }

  2. Comparer<T>和 IComparer<T>的區別:

    • Comparer<T>是類,並提供了默認比較器,也就是說,如果需要自定義默認比較器,需要自行實現IComparer<T>接口
    • 使用Comparer<T>.Default來獲取默認比較器
    • IComparer<T> 就是提供一個統一的比較接口,而Comparer<T>就是官方為你提供的一個抽象實現類,具體還是得要你重寫實現

三. IComparable<T>

自己設計的模型類需要比較,可繼承此接口,實現后就可以直接使用排序
接口類:
1 public interface IComparable<in T>
2 {
3     int CompareTo(T other);
4 }

 

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

  1 class Test
  2 {
  3     static void Main(string[] args)
  4     {
  5         List<Box> Boxes = new List<Box>();
  6         Boxes.Add(new Box(4, 20, 14));
  7         Boxes.Add(new Box(12, 12, 12));
  8         Boxes.Add(new Box(8, 20, 10));
  9         Boxes.Add(new Box(6, 10, 2));
 10         Boxes.Add(new Box(2, 8, 4));
 11         Boxes.Add(new Box(2, 6, 8));
 12         Boxes.Add(new Box(4, 12, 20));
 13         Boxes.Add(new Box(18, 10, 4));
 14         Boxes.Add(new Box(24, 4, 18));
 15         Boxes.Add(new Box(10, 4, 16));
 16         Boxes.Add(new Box(10, 2, 10));
 17         Boxes.Add(new Box(6, 18, 2));
 18         Boxes.Add(new Box(8, 12, 4));
 19         Boxes.Add(new Box(12, 10, 8));
 20         Boxes.Add(new Box(14, 6, 6));
 21         Boxes.Add(new Box(16, 6, 16));
 22         Boxes.Add(new Box(2, 8, 12));
 23         Boxes.Add(new Box(4, 24, 8));
 24         Boxes.Add(new Box(8, 6, 20));
 25         Boxes.Add(new Box(18, 18, 12));
 26 
 27         //使用繼承了Comparer<T>的比較器,進行排序。里面覆寫了Compare(T a,T b)方法
 28         Boxes.Sort(new BoxLengthFirst());  
 29 
 30         foreach (Box bx in Boxes)
 31         {
 32             Console.WriteLine("{0}\t{1}\t{2}",
 33                 bx.Height.ToString(), bx.Length.ToString(),
 34                 bx.Width.ToString());
 35         }
 36 
 37         Console.WriteLine("===============");
 38 
 39         //獲取默認比較器
 40         Comparer<Box> defComp = Comparer<Box>.Default;  
 41 
 42         // Calling Boxes.Sort() with no parameter
 43         // is the same as calling Boxs.Sort(defComp)
 44         // because they are both using the default comparer.
 45         // 等於調用Boxs.Sort(defComp);
 46         Boxes.Sort();
 47 
 48         foreach (Box bx in Boxes)
 49         {
 50             //輸出高、長、寬
 51             Console.WriteLine("{0}\t{1}\t{2}",
 52                 bx.Height.ToString(), bx.Length.ToString(),
 53                 bx.Width.ToString());
 54         }
 55 
 56         // This explicit interface implementation
 57         // compares first by the length.
 58         // Returns -1 because the length of BoxA
 59         // is less than the length of BoxB.
 60         BoxLengthFirst LengthFirst = new BoxLengthFirst();
 61 
 62         Comparer<Box> bc = (Comparer<Box>)LengthFirst;
 63 
 64         Box BoxA = new Box(2, 6, 8);
 65         Box BoxB = new Box(10, 12, 14);
 66         int x = LengthFirst.Compare(BoxA, BoxB);
 67         Console.WriteLine();
 68         Console.WriteLine(x.ToString());
 69  
 70         Console.ReadLine();
 71     }
 72 }
 73 public class BoxLengthFirst : Comparer<Box>
 74 {
 75     //父類抽象方法 Compare
 76     // Compares by Length, Height, and Width.
 77     public override int Compare(Box x, Box y)
 78     {
 79         if (x.Length.CompareTo(y.Length) != 0)
 80         {
 81             return x.Length.CompareTo(y.Length);
 82         }
 83         else if (x.Height.CompareTo(y.Height) != 0)
 84         {
 85             return x.Height.CompareTo(y.Height);
 86         }
 87         else if (x.Width.CompareTo(y.Width) != 0)
 88         {
 89             return x.Width.CompareTo(y.Width);
 90         }
 91         else
 92         {
 93             return 0;
 94         }
 95     }
 96 
 97 }
 98 
 99 
100 // This class is not demonstrated in the Main method
101 // and is provided only to show how to implement
102 // the interface. It is recommended to derive
103 // from Comparer<T> instead of implementing IComparer<T>.
104 
105 //沒有在Main方法里演示,推薦使用繼承Comparer<T>的方法。
106 public class BoxComp : IComparer<Box>
107 {
108     // Compares by Height, Length, and Width.
109     public int Compare(Box x, Box y)
110     {
111         if (x.Height.CompareTo(y.Height) != 0)
112         {
113             return x.Height.CompareTo(y.Height);
114         }
115         else if (x.Length.CompareTo(y.Length) != 0)
116         {
117             return x.Length.CompareTo(y.Length);
118         }
119         else if (x.Width.CompareTo(y.Width) != 0)
120         {
121             return x.Width.CompareTo(y.Width);
122         }
123         else
124         {
125             return 0;
126         }
127     }
128 }
129 
130 public class Box : IComparable<Box>
131 {
132     public Box(int h, int l, int w)
133     {
134         this.Height = h;
135         this.Length = l;
136         this.Width = w;
137     }
138     public int Height { get; private set; }
139     public int Length { get; private set; }
140     public int Width { get; private set; }
141 
142     public int CompareTo(Box other)
143     {
144         // Compares Height, Length, and Width.
145         if (this.Height.CompareTo(other.Height) != 0)
146         {
147             return this.Height.CompareTo(other.Height);
148         }
149         else if (this.Length.CompareTo(other.Length) != 0)
150         {
151             return this.Length.CompareTo(other.Length);
152         }
153         else if (this.Width.CompareTo(other.Width) != 0)
154         {
155             return this.Width.CompareTo(other.Width);
156         }
157         else
158         {
159             return 0;
160         }
161     }
162 }

 

五. Comparison<T>、 Comparer<T>、 System.IComparable、IComparable<T>的區別

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

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

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

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

  1. Default 屬性返回的對象使用 System.IComparable<T> 泛型接口來比較兩個對象。 如果類型 T 未實現 System.IComparable<T> 泛型接口,Default 屬性返回使用 System.IComparable 接口的 Comparer<T>

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM