C# IComparable接口、IComparer接口和CompareTo(Object x)方法、Compare()方法


在項目中經常會用到字符串比較,但是有時候對字符串的操作比較多,規則各異。比如有的地方我們需要用排序規則,有的地方需要忽略大小寫,我們該如何寫一個比較容易操作的比較方法呢?重新實現IComparer接口不失為一個好辦法。

 

IComparable.CompareTo 方法

在MSDN上是這么解釋(機器翻譯過來)的:

IComparable接口:定義一種特定於類型的通用比較方法,值類型或類通過實現此方法對其實例進行排序。

IComparer接口:公開一種比較兩個對象的方法。

 

詳細理解就是:

在默認情況下,對象的Equals(object o)方法(基類Object提供),是比較兩個對象變量是否引用同一對象。

我們要必須我們自己的對象,必須自己定義對象比較方式。

IComparable和ICompare 接口是.net framework 中比較對象的標准方式,這兩個接口之間的區別如下:

IComparable是標識這個類型具有比較的能力,可以比較該對象和另一個對象。一般情況下,我們使用 IComparable 給出類的默認比較代碼,使用其他類給出非默認的比較代碼。中文應該叫“可比較對象”。

IComparer是在一個單獨的類中實現,是指當前對象可以用來比較任意兩個對象,而當前對象本身不參與計算,中文應該叫“比較器”。

CompareTo:IComparable提供了一個方法int CompareTo(object obj)。這個方法接受一個對象,將當前實例的對象與同一類型的另一個對象進行比較,並返回一個整數,該整數指示當前實例在排序順序中的位置是位於另一個對象之前、之后還是與其位置相同。

Compare:IComparer 也提供了一個方法 Compare().這個方法接受兩個對象,返回一個整型結果,這與 CompareTo()相同。

 

IComparable接口

比如:有一個默認實例對象person1,需要和person2判斷,判斷person1是否比person2更年老或年輕,實際上,這個方法返回一個int,所以可和下面的代碼說明person1更年老還是更年輕。

 1  if(person1.CompareTo(person2) == 0)
 2  {
 3    Console.WriteLine("Same age");//年齡一樣,person1和person2比較后返回0
 4  }
 5  else if(person1.CompareTo(person2) > 0 )
 6  {
 7    Console.WriteLine("person1 is older");//如果person1>person2,person1和person2比較后返回正整數,person1比person2年齡大
 8  }
 9  else
10 {
11    Console.WriteLine("person1 is younger");//如上述if不成立,person1<person2,person1和person2比較后返回正整數,person1比person2年齡小
12  }

 

IComparer接口 

同樣適用person來做例子

比如:有一個對象person1,需要和person2判斷,判斷person1是否比person2更年老或年輕,實際上,這個方法同樣也是返回一個int,但是我們使用的是另外的接口(IComparer)的Compare來寫,所以可和下面的代碼說明person1更年老還是更年輕。

 1 if(personComparer.Compare(person1,person2) == 0)
 2 {
 3   Console.WriteLine("same age");
 4 }
 5 else if(personComparer.Compare(person1,person2) > 0 )
 6 {
 7   Console.WriteLine("person 1 is older");
 8 }
 9 else
10 {
11   Console.WriteLine("person1 is younger");
12 }

在這兩種情況下,提供給方法的參數(person1、person2)是system.object類型。也就是說,可以比較任意類型的兩個對象。所以,在返回結果之前,通常需要進行某種類型比較,如果使用了錯誤的類型,還會拋出異常。實際上,我們是使用泛型接口IComparable<T>,可以省略對象轉換。

對象之間的大小比較,在開發過程中用的還是很多的,比如:string是一個可比較對象,它具有和另外一個String比較的能力,它會使用字母序進行比較。但是,有時候我們的一些邏輯需要一些特殊的比較方法。例如:WindowsExplorer 中的文件排序會認為”File10.txt" > "File2.txt"。這時候,我們就需要寫一個特殊的IComparer對象實現這些特定的邏輯。

 

-----------------------------------------------------------------------------分割線-----------------------------------------------------------------------------

 

IComparable.CompareTo(Object x)的比較方式:

compareTo()的返回值是整型類型,它是先比較對應字符的大小(ASCII碼順序),如果第一個字符和另一個參數的第一個字符不等,結束比較,返回他們ASCII碼之間的差值,如果第一個字符和另一個參數的第一個字符相等,則以第二個

字符和另一個參數的第二個字符做比較,以此類推,直至比較的字符或被比較的字符有一方全比較完,這時就比較字符的長度. 

舉個Java的例子說明:

String s1 = "abc"; 
String s2 = "abcd"; 
String s3 = "abcdefg"; 
String s4 = "1bcdfg"; 
String s5 = "cdfg"; 
System.out.println( s1.compareTo(s2) ); // -1 (前面相等,s1長度小1) 
System.out.println( s1.compareTo(s3) ); // -4 (前面相等,s1長度小4) 
System.out.println( s1.compareTo(s4) ); // 48 ("a"的ASCII碼是97,"1"的的ASCII碼是49,所以返回48) 
System.out.println( s1.compareTo(s5) ); // -2 ("a"的ASCII碼是97,"c"的ASCII碼是99,所以返回-2)

 -----------------------------------------------------------------------------分割線-----------------------------------------------------------------------------

C# 如何實現compareTo()方法

那么在什么時候使用Icomparable.CompareTo(object obj)方法呢?

如果一個類實現了Icomparable接口,就可以重寫Icomparable接口中的CompareTo(object obj)方法,假設集合中有幾個學員對象,要按學員的姓名進行排序,那么就可以重寫CompareTo方法按姓名排序,但如果又想按年齡排序了怎么辦?CompareTo方法只能重寫一次啊,這時就可以用到Icompare了。Icompare就叫做比較器,集合默認的Sort()排序方法有種重載的參數就是Icompare比較器對象。

像所有集合類一樣,它允許您對所有實現了IComparable接口的對象進行排序。在下一個例子中,您將修改NameCompare類以實現IComparable的泛型接口:

public class NameCompare: IComparable<Student>

實現IComparable<Student>接口,NameCompare對象必須提供CompareTo()方法:

 1 class NameCompare:IComparer<Student>     //姓名升序
 2 {
 3    public int Compare(Student x, Student y) 
 4    {
 5         return x.Name.CompareTo(y.Name);
 6    }
 7 }
 8 
 9 class NameCompare1 : IComparer<Student>     //姓名降序
10 {
11     public int Compare(Student x, Student y)
12     {
13         return y.Name.CompareTo(x.Name);
14     }
15 }
16 
17 class AgeCompare : IComparer<Student> 
18 {
19     public int Compare(Student x, Student y) 
20     {
21         return x.Age.CompareTo(y.Age);
22     }
23 }

要排序的時候:

 1 private void button3_Click(object sender, EventArgs e)
 2 {
 3     init();
 4     students.Sort(new NameCompare());               //姓名升序,Sort方法的參數就是實現了Icompare接口的類的對象
 5     show(students);
 6 }
 7 
 8 private void button4_Click(object sender, EventArgs e)
 9 {
10     init();
11     students.Sort(new NameCompare1());          //姓名降序
12     show(students);
13 }
14 
15 private void button5_Click(object sender, EventArgs e)
16 {
17     init();
18     students.Sort(new AgeCompare());
19     show(students);
20 }

 

 

轉發請說明出處:http://www.cnblogs.com/abc1069/p/3993818.html


免責聲明!

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



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