我們知道,與C++相比較,C#以及整個.Net並不支持多繼承,而相應的,C#支持了接口,並且支持一個類型實現多個接口。對於接口的概念,相信大部分讀者已經有了很好的了解,而我這裡談談個人對於接口理解,只求拋磚引玉。
在我認為,一個接口就是一個對類型的某種能力的認證,並且是以某種標准化的形式將這種能力規范出來。你的類型實現了某個接口,換而言之,也就是說這個類型具備了此接口所標識的能力。比如現在出國留學考托福GRE,開車考駕照這些東西,其實就是相當於我們編程中接口;從某種意義上說,你通過了GRE,就說明你具備在國外學習所需要的語言能力,而你考取了駕照,就證明了你具有上路行駛的能力了。接口同樣如此,給你類型實現特定的一些接口,就是給他們標記了他們所具備的特別能力,而一些依賴這些能力的功能,得以用通用的代碼實現重用,實現可擴展。
我的這個關於接口的系列文章,主要是對.Net編程一些非常重要的接口來進行詳細講解,深入了解這些接口的原理和應用。這對於我們寫出精簡優美的代碼,是非常有幫助的;畢竟,我們在知道自己想做什麼之後,首先應該知道.Net Framework能給我們做什麼。
在本篇以及後續的幾篇文章我們將會談到以下幾個主題:
(一)比較和排序(IComparable和IComparer)
(二)枚舉(IEnumerable和IEnumerator)
(三) 序列化(ISerializable和IXMLSerializable)
System.IComparable & System.IComparable<T>
顧名思義,一個實現了IComparable的class應該就是一個可以對實例進行相互比較的class,我們先來看看它的定義:
[ComVisible(true)]
public interface IComparable
{
int CompareTo(object obj);
}
這個接口相當簡單,只提供了一個接口函數:CompareTo,如果當前對象比被比較的對象小,那麼返回負數;如果相當,則返回0;如果當前對象比被比較的對象大,則返回正數。
但是,如果你覺得這個接口僅僅是能夠讓你比較兩個對象大小,那麼你就錯了,這個接口更大的作用是能夠實現了該類型線性數據結構的排序功能。比如List<T>.Sort()和Array的靜態方法Sort都能夠很好地利用IComparable來對數據進行排序,排序算法由類庫實現,對於我們來說,只需要讓自己的類型實現IComparable接口,負責比較兩個對象大小的算法就可以了。
IComparable<T>是一個泛型接口,用於實現對特定類型的對象的比較,用法和IComparable基本一致,這裡不再進行贅述,下面的例子也是根據IComparable來寫的。
我們來看看下面的代碼,這裡定義了一個學生類Student,每個學生有自己名字和分數。Student類實現了IComparable接口,兩個學生之間直接按照名字進行比較。順便說明Scores類用於存儲學生的成績。
public enum SubjectEnum
{
Total =0,
Chinese,
English,
Math,
}
public class Scores //分數類,用於存儲分數
{
int[] _score = new int[4];
public int this[SubjectEnum score]
{
get { return _score[(int)score]; }
set { _score[(int)score] = value; }
}
public override string ToString()
{
string str = "";
foreach (int score in _score)
{
str += " " + score.ToString();
}
return str;
}
}
public class Student:IComparable //學生類
{
string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
Scores _scores=new Scores();
public Scores Scores
{
get { return _scores; }
set { _scores = value; }
}
public Student(string name,int chinese, int english, int math)
{
_name = name;
_scores[SubjectEnum.Chinese] = chinese;
_scores[SubjectEnum.English] = english;
_scores[SubjectEnum.Math] = math;
_scores[SubjectEnum.Total] = chinese +english +math;
}
public override string ToString()
{
return _name + _scores.ToString();
}
#region IComparable Members
public int CompareTo(object obj)
{
if (!(obj is Student))
throw new ArgumentException("Argument not a Student", "obj");
return Name.CompareTo(((Student)obj).Name);
}
#endregion
}