學生有名稱、學號,html
班級有班級名稱、班級序號git
學校有學校名稱、學校編號(序號)github
如今須要對學生進行排序數據庫
第一排序邏輯this
固然,在咱們錄入數據庫信息的時候,有的人可能比較懶,沒有錄入 學校的序號, 班級的序號,學生的學號 ,怎麼辦? 那麼就Plan B !spa
第二排序邏輯code
我編寫了學校、班級、學生的實體關係代碼以下:htm
namespace Sort { public class School { public int? Order { get; set; } public string Name { get; set; } } public class Class { public int? Order { get; set; } public string Name { get; set; } public School School { get; set; } } public class Student { public int? Order { get; set; } public string Name { get; set; } public Class Class { get; set; } } }
之前寫的簡單排序,還能夠用OrderBy解決,若是以前寫過的一篇文章:blog
可是這裏的排序就比較複雜了,用簡單的OrderBy恐怕是解決不了了。
.Net中,對List集合,有一個Sort字方法,讓咱們選中Sort方法,F12,看看Sort方法長哪樣?
能夠看到Sort方法一共有四個重載,咱們挑最基礎的一個,Sort() 0參數的這個,懂了這個,其餘幾個應該也會懂了,咱們看看該方法的描述:
雖然我英語不太好,可是這基礎的英語仍是能看懂,大體是說:
用默認的比較器對該List進行排序。
那麼,這個Comparer(比較器)是什麼呢?
其實,它是接口IComparable下的一個方法,也就是說只有實現了ICoparable接口下的這個叫比較器的方法才能使用Sort進行排序,咱們F12進入到IComparable來看看這個接口:
能夠看到,該接口只有一個CompareTo方法,我用我蹩腳的英語大體看懂了這句話的意思是:
定義一個比較方法來對制定類型進行排序。
該方法返回類型爲Int類型。經過查找查找相關資料,瞭解到其返回值與其含義以下:
值 |
含義 |
複數 |
該實例比傳入的Other實例小。 |
0 |
該實例與傳入的Other實例相等。 |
正數 |
該實例比傳入的Other實例大。 |
知道了這個原則,咱們就能夠給Student類繼承並實現該方法了。
對文章開頭的排序需求,咱們重溫一下:
第一排序邏輯(Int?)
當序號爲空時,用第二種排序邏輯,
第二排序邏輯(String)
其實無非就是對Student中涉及到的Int?和string兩種數據類型進行比較。
Int?類型(Nullable)和string已經實現了Compare方法,其中Nullable的以下:
可是爲了能更深刻地理解該方法的使用,我本身來寫一個Int?類型數據比較的方法,以下:
private int CompareInit(int? x, int? y) { if (x == null && y == null) //若是都是空 那麼返回0相等 return 0; if (x.HasValue && y == null) //若是傳入X有值,可是Y是空的,那麼X比Y小 返回-1。 return -1; if (x == null && y.HasValue) //若是傳入X爲空,可是Y有值,那麼X比Y大 返回1。 return 1; if (x.Value > y.Value) return 1; if (x.Value < y.Value) return -1; return 0; //不然兩個數相等 }
其中,爲何我認爲有值的比Null的還小返回-1呢? 由於我想把Null的日後排,把有值的往前排,其餘流行的作法是認爲有值的是比Null大的,即返回1,你們能夠結合本身的業務需求選擇。
寫好了Int?類型數據比較的方法,還有String類型數據的比較,我就不本身造輪子去寫了,用現成的String.CompareOrdinal()方法。
而後,咱們開始給Student實現ICompare接口的CompareTo方法,以下:
public class Student : IComparable<Student> { public int? Order { get; set; } public string Name { get; set; } public Class Class { get; set; } public int CompareTo(Student other) { if (ReferenceEquals(this, other)) return 0; //若是兩個值的引用相同,那麼直接返回相等。 if (ReferenceEquals(null, other)) return 1; //若是該實例是空的,可是傳入的實例不是空的,那麼返回1 //比較學校的序號 var compareResult = CompareInit(this.Class.School.Order, other.Class.School.Order); if (compareResult != 0) return compareResult; //比較班級的序號 compareResult = CompareInit(this.Class.Order, other.Class.Order); if (compareResult != 0) return compareResult; //比較學生的學號 compareResult = CompareInit(this.Order, other.Order); if (compareResult != 0) return compareResult; //若是以上還未區分出大小,比較學校的名稱 compareResult = String.CompareOrdinal(this.Class.School.Name, other.Class.School.Name); if (compareResult != 0) return compareResult; //比較班級的名稱 compareResult = String.CompareOrdinal(this.Class.Name, other.Class.Name); if (compareResult != 0) return compareResult; //比較學生的名稱 return String.CompareOrdinal(this.Name, other.Name); }
實現該方法後,就能夠對List<Student> 使用Sort方法了,咱們來試試看。
using System; using System.Collections.Generic; namespace Sort { class Program { static void Main(string[] args) { var students = InitData(); students.Sort(); //此處執行了Sort方法 Console.WriteLine("Name-Order"); foreach (var student in students) { Console.WriteLine($"學校:{student.Class.School.Name}-{student.Class.School.Order}>>班級:{student.Class.Name}-{student.Class.Order}>>學生:{student.Name}-{student.Order}"); } Console.ReadLine(); } static List<Student> InitData() //建立數據 { var school1 = new School() { Order = 1, Name = "A", }; var school2 = new School { Name = "B", Order = 0 }; var class1 = new Class { Order = 1, Name = "1", School = school1, }; var class2 = new Class { Order = 2, Name = "2", School = school1, }; var class3 = new Class { Order = 1, Name = "1", School = school2, }; var student1 = new Student { Order = 1, Name = "1", Class = class1, }; var student2 = new Student { Order = 2, Name = "2", Class = class1, }; var student3 = new Student { Order = 3, Name = "3", Class = class1, }; var student4 = new Student { Order = 1, Name = "1", Class = class2, }; var student5 = new Student { Order = 1, Name = "1", Class = class3, }; return new List<Student> { student5, student3, student4, student2, student1 }; } } }
執行效果以下:
能夠看到,學校B雖然是以B開頭,可是由於期Order爲0比1更靠前,因此以Order爲準,學校B排到了最前面。
好幾天沒寫了,寫博客對我我而言,意義無非在於加深印象同時把我所掌握的東西分享給你們,這個方法是今天同事教個人,可能對園子裏大神來講這比較基礎,可是相信若是掌握這個方法,對之後也許中複雜排序會有比較有用,但願對你們也能有所幫助。
項目的GitHub地址:
https://github.com/liuzhenyulive/Sort
若是你們有更好的辦法,歡迎下下方留言與我交流。