在Linq中排序操做能夠按照一個或多個關鍵字對序列進行排序。其中第一個排序關鍵字爲主要關鍵字,第二個排序關鍵字爲次要關鍵字。Linq排序操做共包含如下5個基本的操做。web
一、OrderBy操做,根據排序關鍵字對序列進行升序排序函數
二、OrderByDescending操做,根據排序關鍵字對序列進行降序排序測試
三、ThenBy操做,對次要關鍵字進行升序排序this
四、ThenByDescending操做,對次要關鍵字進行降序排序spa
五、Reverse操做,將序列中的元素進行反轉3d
那麼下面咱們就逐一來分析一下每一個排序操做。code
OrderBy操做blog
OrderBy操做是按照主關鍵字對序列進行升序排序的操做。Enumerable類的OrderBy()原型以下:排序
1、public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { return new OrderedEnumerable<TSource, TKey>(source, keySelector, null, false); } 2、public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) { return new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, false); }
其中source表示數據源,keySelector表示獲取排序的關鍵字的函數,comparer參數表示排序時的比較函數。TSource表示數據源的類型,TKey表示排序關鍵字的類型。下面咱們用兩種方式來比較排序,第一種按照前面講的查詢表達式來排序,第二種用如今的排序操做來排序,其實結果都是同樣的。接口
private void OrderByQuery() { int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 }; //使用查詢表達式來排序 Response.Write("--------------使用查詢表達式來排序---------</br>"); var values = from v in ints orderby v select v; foreach (var item in values) { Response.Write(item+"</br>"); } //使用排序操做來排序 Response.Write("--------------使用排序操做來排序---------</br>"); var result = ints.OrderBy(x => x); foreach (var re in result) { Response.Write(re + "</br>"); } }
看看運行結果:
咱們看到和咱們預想的是同樣的。那麼你們可能有些疑問,爲何OrderBy是升序排序呢?
咱們來從源碼解析一下:
咱們看到OrderBy裏面最終調用了一個函數OrderedEnumerable,那麼咱們再來看看這個OrderedEnumerable函數:
看到這個函數有一個參數descending,咱們OrderBy方法給這個參數傳了false,那麼就表示非降序排序,就是升序排序。可想而知,OrderByDescending操做,給這個參數傳值應該是true。
第二個原型裏面有個comparer參數,那麼咱們來看看怎麼用:既然是IComparer接口類型的參數,那麼咱們就定義一個實現了Icomparer接口的類型:
1 private void OrderByQuery() 2 { 3 int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 }; 4 5 6 var result = ints.OrderBy(x => x,new CompareIntegers()); 7 8 foreach (var re in result) 9 { 10 11 Response.Write(re + "</br>"); 12 } 13 14 } 15 16 public class CompareIntegers : IComparer<int> 17 { 18 public int Compare(int i1, int i2) 19 { 20 return -1*(i1 - i2); 21 } 22 }
咱們看到,咱們定義的CompareIntegers類的比較參數是,該元素取反,因此排序結果應該就成了降序排序了。咱們看看測試結果:
嗯和咱們預想的同樣,這個comparer函數就是咱們自定義的比較方式。
OrderByDescending操做
OrderByDescending和咱們上面的OrderBy操做類似,最終都是調用OrderedEnumerable只是傳入的descending參數的值不一樣。看看OrderByDescending的原型:
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector); public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer);
也有兩個原型,跟OrderBy的原型如出一轍,只是最終調用OrderedEnumerable方法的傳入參數不一樣。
咱們看到這個傳入的是true,表示降序排列。因此我我的以爲這兩個操做能夠合併,而後多一個參數而已。
一樣寫個例子測試一下:
1 private void OrderByDescendingQuery() 2 { 3 int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 }; 4 5 //使用查詢表達式來排序 6 7 Response.Write("--------------使用查詢表達式來排序---------</br>"); 8 var values = from v in ints 9 10 orderby v descending 11 12 select v; 13 14 foreach (var item in values) 15 { 16 17 Response.Write(item+"</br>"); 18 } 19 //使用排序操做來排序 20 21 Response.Write("--------------使用排序操做來排序---------</br>"); 22 23 var result = ints.OrderByDescending(x => x); 24 25 foreach (var re in result) 26 { 27 28 Response.Write(re + "</br>"); 29 } 30 31 }
看看測試結果:
嗯結果和預想的同樣。
ThenBy操做
上面兩個排序都是按照主關鍵字來排序的,下面呢咱們就看看什麼是按照次要關鍵字排序。ThenBy 和OrderBy同樣是按照升序排序的。來看看原型:
public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector); public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer);
原型和OrderBy同樣。可是ThenBy必需要和OrderBy配合使用。就是 必需要先有OrderBy排序,而後再用ThenBy排序。不可以直接用ThenBy排序。
一樣咱們寫個例子一看便知。這個例子呢咱們每一個序列的每一個元素至少要有兩個字段,一個作主關鍵字,一個作次要關鍵字。咱們仍是用前面將的UserBaseInfo來建立例子,用ID作主關鍵字,username作次要關鍵字。
1 private void ThenByQuery() 2 { 3 IList<UserBaseInfo> users = new List<UserBaseInfo>(); 4 5 for (int i = 1; i < 10; i++) 6 { 7 users.Add(new UserBaseInfo(i, "user0" + i.ToString(), "user0" + i.ToString() + "@web.com")); 8 } 9 10 var values = users.OrderBy(u => u.ID).ThenBy(x => x.UserName); 11 12 foreach (var u in values) 13 { 14 Response.Write("ID:" + u.ID + "</br>" + "username:" + u.UserName + "</br>"); 15 } 16 17 18 }
看看結果:
ThenByDescending操做
這個是ThenBy的降序排序方式,和前面的用法實質是同樣的,我就不詳細講解了,你們能夠本身研究一下。
Reverse操做
下面咱們就來看看Reverse這個排序。這個排序呢能夠說也不算是排序,由於咱們知道排序無非就是升序,或者降序。這個其實就是將一個序列進行反轉,裏面的值若是原本沒有順序,執行這個操做以後,也不會變得有序,只是序列的元素反轉。
看看reverse的原型:
public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source);
測試樣例:
1 private void ReverseQuery() 2 { 3 IList<UserBaseInfo> users = new List<UserBaseInfo>(); 4 5 for (int i = 1; i < 10; i++) 6 { 7 users.Add(new UserBaseInfo(i, "user0" + i.ToString(), "user0" + i.ToString() + "@web.com")); 8 } 9 10 var values = users.Reverse(); 11 12 foreach (var u in values) 13 { 14 Response.Write("ID:" + u.ID + "</br>" + "username:" + u.UserName + "</br>"); 15 } 16 17 18 }
運行結果:
看確實是反轉了。
再看一個原本無序的例子。
1 private void ReverseQuery() 2 { 3 int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 }; 4 5 6 var result = ints.Reverse(); 7 8 foreach (var re in result) 9 { 10 11 Response.Write(re + "</br>"); 12 } 13 14 }
運行結果:
能夠看出,只是把序列的元素反轉了,並不會進行升序或者降序排序。
咱們來看看內部實現,內部實現其實很簡單:
就是對序列反向輸出。