公司最近進了個實習生,天天下班前我都會花一些時間來解答一下實習生的一些疑問。今天問起了關於集合排序方法Sort的一些疑問,這讓我一下回到本身剛剛入行的時候。那個時候也遇到了集合排序的問題,爲發現接口IComparable和ICompare的妙處而興奮,還在公司的內部分享會上分享瞭如何使用它們來排序。如今通過多年的開發實踐以及學習,對於同一個問題又有了更加深刻的理解。html
實習生先是問了這個問題, 其實這個問題, 很是容易解答.
先來看看IEnumerable接口的定義:函數
public interface IEnumerable { IEnumerator GetEnumerator(); }
這個接口很是簡單,主要就是一個方法GetEnumerator,用來返回一個IEnumerator對象。
繼續深刻下去,IEnumerator接口的定義以下:學習
public interface IEnumerator { bool MoveNext(); void Reset(); object Current { get; } }
上面的IEnumerator接口定義的屬性和方法,只有一個目的,就是實現如何遍歷。下面具體解釋一下:spa
到這裏,爲何foreach可以遍歷集合對象的緣由就是由於集合對象都實現了IEnumerable接口,提供了具體的實現來遍歷集合對象。設計
集合類型,都有Sort()排序方法,這個函數的一個重載版本中,須要提供一個IComparer類型的接口。爲何須要使用這個接口呢?這個和排序有什麼關係?
想想,實現排序必須的是什麼?必須的是可以比較大小。對於int, string這種.Net內部類型,自己已經支持了IComparer, 也就是能夠比較大小了。可是對於咱們本身定義的類型,使用Sort方法是沒法排序的,由於程序不知道咱們對於自定義對象的排序規則, 這個時候就可使用IComparable、IComparer.3d
下面舉一個實際的例子, 這裏咱們自定義了一個類Car, 而後對Car的集合進行排序.code
public class Car { public string Name { get; set; } public int Year { get; set; } public int Seats { get; set; } }
假如咱們直接調用Sort方法, 就會悲劇拋出InvalidOperationException異常htm
IComparable 接口提供了比較某個特定類型對象的方法. 這裏來講, 咱們要讓Car實現IComparable 接口來達到比較Car對象的目的,從而實現排序。實現IComparable接口, 就必須實現CompareTo 方法, 具體以下:對象
public class Car: IComparable { public string Name { get; set; } public int Year { get; set; } public int Seats { get; set; } public int CompareTo(object obj) { var car = (Car) obj; return String.CompareOrdinal(Name, car.Name); } }
上面咱們的Car對象實現了IComparable接口,按照Name字符串屬性來比較. 直接運行Sort()方法,就可以獲得排序結果:blog
IComparer接口能夠提供更加豐富和靈活的排序功能。 好比, 你可能須要在不一樣的場合,根據不一樣的屬性來排序.
下面就來實現一個根據Car的Year屬性來排序, 首先建立類CarYearComparer來對Car進行比較,比較是根據Year屬性
public class CarYearComparer: IComparer<Car> { public int Compare(Car x, Car y) { if (x.Year > y.Year) return 1; if (x.Year < y.Year) return -1; return 0; } }
在調用Sort方法排序的時候,須要指定使用的IComparer實現:
cars.Sort(new CarYearComparer());
獲得的排序結果和上面的根據Name屬性不一樣:
還能夠實現一個根據Car的屬性Seats排序的IComparer. 因此使用IComparer更加的靈活
Collection中的Sort()方法很好地遵循了開放封閉原則,既很好地完成了排序的功能,同時又開放出了入口,讓你能夠爲排序自定義規則。
下面是我我的的一些我的理解:
一個類應該作本身擅長的事情和核心的事情(單一職責),把不擅長的交給別人。可是這個」別人「是否是任何人均可以呢?固然不是,爲了更好的限定別人,咱們使用了接口限定。
當一個類依賴於抽象(也就是接口),那麼這個類的適用範圍就更加廣,就可以更加超脫。老子一句」道可道,很是道;名可名,很是名」,正是沒有具體化,因此能夠解釋萬物。
更多的面向對象設計原則,參照http://www.360doc.com/content/11/0521/00/3554006_118258005.shtml
最後附上本文相關源代碼: SortDemo