引用
最近總有種感覺,自己復習的進度總被項目中的問題給耽擱了,項目中遇到的問題,不總結又不行,只能將復習基礎方面的東西放后再放后。一直沒研究過太深奧的東西,過去一年一直在基礎上打轉,寫代碼,反編譯,不停的重復。一直相信,在你不知道要干嘛的時候,浮躁的時候,不如回到最基礎的東西上,或許換種思考方式,會有不一樣的收獲。
泛型集合List<T>排序
先看一個簡單的例子,int類型的集合:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 namespace Wolfy.SortDemo 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 List<int> list = new List<int>() { 3, 4, 5, -2, -5, 11, 23, }; 13 Console.WriteLine("排序前...."); 14 foreach (int item in list) 15 { 16 Console.Write(item+"\t"); 17 } 18 list.Sort(); 19 Console.WriteLine(); 20 Console.WriteLine("排序后...."); 21 foreach (int item in list) 22 { 23 Console.Write(item+"\t"); 24 } 25 Console.Read(); 26 } 27 } 28 }
經sort方法之后,采用了升序的方式進行排列的。
集合的Sort方法

1 // 2 // 摘要: 3 // 使用默認比較器對整個 System.Collections.Generic.List<T> 中的元素進行排序。 4 // 5 // 異常: 6 // System.InvalidOperationException: 7 // 默認比較器 System.Collections.Generic.Comparer<T>.Default 找不到 T 類型的 System.IComparable<T> 8 // 泛型接口或 System.IComparable 接口的實現。 9 public void Sort(); 10 // 11 // 摘要: 12 // 使用指定的 System.Comparison<T> 對整個 System.Collections.Generic.List<T> 中的元素進行排序。 13 // 14 // 參數: 15 // comparison: 16 // 比較元素時要使用的 System.Comparison<T>。 17 // 18 // 異常: 19 // System.ArgumentNullException: 20 // comparison 為 null。 21 // 22 // System.ArgumentException: 23 // 在排序過程中,comparison 的實現會導致錯誤。 例如,將某個項與其自身進行比較時,comparison 可能不返回 0。 24 public void Sort(Comparison<T> comparison); 25 // 26 // 摘要: 27 // 使用指定的比較器對整個 System.Collections.Generic.List<T> 中的元素進行排序。 28 // 29 // 參數: 30 // comparer: 31 // 比較元素時要使用的 System.Collections.Generic.IComparer<T> 實現,或者為 null,表示使用默認比較器 System.Collections.Generic.Comparer<T>.Default。 32 // 33 // 異常: 34 // System.InvalidOperationException: 35 // comparer 為 null,且默認比較器 System.Collections.Generic.Comparer<T>.Default 找不到 36 // T 類型的 System.IComparable<T> 泛型接口或 System.IComparable 接口的實現。 37 // 38 // System.ArgumentException: 39 // comparer 的實現導致排序時出現錯誤。 例如,將某個項與其自身進行比較時,comparer 可能不返回 0。 40 public void Sort(IComparer<T> comparer); 41 // 42 // 摘要: 43 // 使用指定的比較器對 System.Collections.Generic.List<T> 中某個范圍內的元素進行排序。 44 // 45 // 參數: 46 // index: 47 // 要排序的范圍的從零開始的起始索引。 48 // 49 // count: 50 // 要排序的范圍的長度。 51 // 52 // comparer: 53 // 比較元素時要使用的 System.Collections.Generic.IComparer<T> 實現,或者為 null,表示使用默認比較器 System.Collections.Generic.Comparer<T>.Default。 54 // 55 // 異常: 56 // System.ArgumentOutOfRangeException: 57 // index 小於 0。 - 或 - count 小於 0。 58 // 59 // System.ArgumentException: 60 // index 和 count 未指定 System.Collections.Generic.List<T> 中的有效范圍。 - 或 - comparer 61 // 的實現導致排序時出現錯誤。 例如,將某個項與其自身進行比較時,comparer 可能不返回 0。 62 // 63 // System.InvalidOperationException: 64 // comparer 為 null,且默認比較器 System.Collections.Generic.Comparer<T>.Default 找不到 65 // T 類型的 System.IComparable<T> 泛型接口或 System.IComparable 接口的實現。 66 public void Sort(int index, int count, IComparer<T> comparer);
可見sort方法有三個重載方法。
對自定義類型排序
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Wolfy.SortDemo 8 { 9 public class Person 10 { 11 public string Name { set; get; } 12 public int Age { set; get; } 13 } 14 }
對Person進行sort后輸出,就會出現如下異常:
對自定義的Person類型進行排序,出現異常。那為什么int類型就沒有呢?可以反編譯一下,你會發現:
可見int類型是實現了IComparable這個接口的。那么如果讓自定義類型Person也可以排序,那么試試實現該接口。
修改Person類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Wolfy.SortDemo 8 { 9 public class Person : IComparable 10 { 11 public string Name { set; get; } 12 public int Age { set; get; } 13 14 /// <summary> 15 /// 實現接口中的方法 16 /// </summary> 17 /// <param name="obj"></param> 18 /// <returns></returns> 19 public int CompareTo(object obj) 20 { 21 Person p = obj as Person; 22 //因為int32實現了接口IComparable,那么int也有CompareTo方法,直接調用該方法就行 23 return this.Age.CompareTo(p.Age); 24 } 25 } 26 }
CompareTo方法的參數為要與之進行比較的另一個同類型對象,返回值為int類型,如果返回值大於0,表示第一個對象大於第二個對象,如果返回值小於0,表示第一個對象小於第二個對象,如果返回0,則兩個對象相等。
定義好默認比較規則后,就可以通過不帶參數的Sort方法對集合進行排序。
測試結果:
以上采用的sort()方法排序的結果。
實際使用中,經常需要對集合按照多種不同規則進行排序,這就需要定義其他比較規則,可以在Compare方法中定義,該方法屬於IComparer<T>泛型接口,請看下面的代碼:
1 namespace Wolfy.SortDemo 2 { 3 public class PersonNameDesc:IComparer<Person> 4 { 5 //存放排序器實例 6 public static PersonNameDesc NameDesc = new PersonNameDesc(); 7 public int Compare(Person x, Person y) 8 { 9 return System.Collections.Comparer.Default.Compare(x.Name, y.Name); 10 } 11 } 12 }
Compare方法的參數為要進行比較的兩個同類型對象,返回值為int類型,返回值處理規則與CompareTo方法相同。其中的Comparer.Default返回一個內置的Comparer對象,用於比較兩個同類型對象。
下面用新定義的這個比較器對集合進行排序:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 List<Person> list = new List<Person>() 6 { 7 new Person(){Name="a",Age=2}, 8 new Person(){Name="d",Age=9}, 9 new Person(){Name="b",Age=3}, 10 new Person(){Name="c",Age=10} 11 }; 12 13 list.Sort(PersonNameDesc.NameDesc); 14 foreach (Person p in list) 15 { 16 Console.WriteLine(p.Name + "\t" + p.Age); 17 } 18 Console.Read(); 19 } 20 }
測試結果:
Sort(int index, int count, IComparer<T> comparer)
同上面的類似,只是這個是取范圍的。
Sort(Comparison<T> comparison)
sort方法的一個重載是Comparison<T>類型的參數,那么Comparison到底是什么東東呢?,說實話,不F12還真發現不了。
1 #region 程序集 mscorlib.dll, v4.0.0.0 2 // C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll 3 #endregion 4 5 namespace System 6 { 7 // 摘要: 8 // 表示比較同一類型的兩個對象的方法。 9 // 10 // 參數: 11 // x: 12 // 要比較的第一個對象。 13 // 14 // y: 15 // 要比較的第二個對象。 16 // 17 // 類型參數: 18 // T: 19 // 要比較的對象的類型。 20 // 21 // 返回結果: 22 // 一個有符號整數,指示 x 與 y 的相對值,如下表所示。 值 含義 小於 0 x 小於 y。 0 x 等於 y。 大於 0 x 大於 y。 23 public delegate int Comparison<in T>(T x, T y); 24 }
看到這里就該笑了,委托啊,那么豈不是可以匿名委托,豈不是更方便啊。那么排序可以這樣了。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 namespace Wolfy.SortDemo 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 List<Person> list = new List<Person>() 13 { 14 new Person(){Name="a",Age=2}, 15 new Person(){Name="b",Age=9}, 16 new Person(){Name="c",Age=3}, 17 new Person(){Name="d",Age=10} 18 }; 19 //匿名委托 20 list.Sort((a,b)=>a.Age-b.Age); 21 foreach (Person p in list) 22 { 23 Console.WriteLine(p.Name + "\t" + p.Age); 24 } 25 Console.Read(); 26 } 27 } 28 }
結果:
使用Linq排序
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 namespace Wolfy.SortDemo 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 List<Person> list = new List<Person>() 13 { 14 new Person(){Name="a",Age=2}, 15 new Person(){Name="d",Age=9}, 16 new Person(){Name="b",Age=3}, 17 new Person(){Name="c",Age=10} 18 }; 19 var l = from p in list 20 orderby p.Age descending 21 select p; 22 //list.Sort(PersonNameDesc.NameDesc); 23 foreach (Person p in l) 24 { 25 Console.WriteLine(p.Name + "\t" + p.Age); 26 } 27 Console.Read(); 28 } 29 } 30 }
總結
從下班弄到現在,一直整理筆記。泛型集合的排序選一個順手的就行。