C#筆記25:比較和排序(IComparable和IComparer以及它們的泛型實現) 本文摘要: 1:比較和排序的概念; 2:IComparable和IComparer; 3:IComparable和IComparer的泛型實現IComparable<T>和IComparer<T>; 1:比較和 ...
C#筆記25:比較和排序(IComparable和IComparer以及它們的泛型實現)
本文摘要:
1:比較和排序的概念;
2:IComparable和IComparer;
3:IComparable和IComparer的泛型實現IComparable<T>和IComparer<T>;
1:比較和排序的概念
比較:兩個實體類之間按>,=,<進行比較。
排序:在集合類中,對集合類中的實體進行排序。排序基於的演算法基於實體類提供的比較函數。
基本型別都提供了預設的比較演算法,如string提供了按字母進行比較,int提供了按整數大小進行比較。
2:IComparable和IComparer
當我們創建了自己的實體類,如Student,預設想要對其按照年齡進行排序,則需要為實體類實現IComparable介面。
class Student:IComparable { public string Name { get; set; } public int Age { get; set; } #region IComparable Members public int CompareTo(object obj) { Student student = obj as Student; if (Age > student.Age) { return 1; } else if (Age == student.Age) { return 0; } else { return -1; } //return Age.CompareTo(student.Age); } #endregion }
PS:註意上面代碼中CompareTo方法有一條註釋的代碼,其實本函數完全可以使用該註釋代碼代替,因為利用了整形的預設比較方法。此處未使用本註釋代碼,是為了更好的說明比較器的工作原理。
接下來寫一個測試用例:
public Form1() { InitializeComponent(); studentList = new ArrayList(); studentList.Add(new Student() { Age = 1, Name = "a1" }); studentList.Add(new Student() { Age = 5, Name = "g1" }); studentList.Add(new Student() { Age = 4, Name = "b1" }); studentList.Add(new Student() { Age = 2, Name = "f1" }); } ArrayList studentList; private void button1_Click(object sender, EventArgs e) { studentList.Sort(); foreach (Student item in studentList) { this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n" ; } }
運行結果:
a1----1
f1----2
b1----4
g1----5
OK,疑問來了。如果不想使用年齡作為比較器了,那怎麼辦。這個時候IComparer的作用就來了,可使用IComparer來實現一個自定義的比較器。如下:
class SortName: IComparer { #region IComparer Members public int Compare(object x, object y) { Student s1 = x as Student; Student s2 = y as Student; return s1.Name.CompareTo(s2.Name); } #endregion }
這個時候,我們在排序的使用為Sort方法提供此比較器:
studentList.Sort(new SortName());
運行的結果是:
a1----1
b1----4
f1----2
g1----5
3:IComparable和IComparer的泛型實現IComparable<T>和IComparer<T>
如果我們稍有經驗,我們就會發現上面的代碼我們使用了一個已經不建議使用的集合類ArrayList。當泛型出來後,所有非泛型集合類已經建議不儘量使用了。至於原因,從上面的代碼中我們也可以看出一點端倪。
註意查看這個Compare函數,如:
public int Compare(object x, object y) { Student s1 = x as Student; Student s2 = y as Student; return s1.Name.CompareTo(s2.Name); }
我們發現這個函數進行了裝箱和拆箱。而這是會影響性能的。如果我們的集合中有成千上萬個複雜的實體對象,則在排序的時候所耗費掉的性能就是客觀的。而泛型的出現,就可以避免掉拆箱和裝箱。
故上文代碼中的ArrayList,應該換成List<T>,對應的,我們就該實現IComparable<T>和IComparer<T>。最終的代碼應該像:
public partial class Form1 : Form { public Form1() { InitializeComponent(); studentList = new List<Student>(); studentList.Add(new Student() { Age = 1, Name = "a1" }); studentList.Add(new Student() { Age = 5, Name = "g1" }); studentList.Add(new Student() { Age = 4, Name = "b1" }); studentList.Add(new Student() { Age = 2, Name = "f1" }); } List<Student> studentList; private void button1_Click(object sender, EventArgs e) { studentList.Sort(new SortName()); foreach (Student item in studentList) { this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n" ; } } } class Student:IComparable<Student> { public string Name { get; set; } public int Age { get; set; } #region IComparable<Student> Members public int CompareTo(Student other) { return Age.CompareTo(other.Age); } #endregion } class SortName: IComparer<Student> { #region IComparer<Student> Members public int Compare(Student x, Student y) { return x.Name.CompareTo(y.Name); } #endregion }