.Net Collection的一些理解——記錄一次向實習生的答疑

公司最近進了個實習生,天天下班前我都會花一些時間來解答一下實習生的一些疑問。今天問起了關於集合排序方法Sort的一些疑問,這讓我一下回到本身剛剛入行的時候。那個時候也遇到了集合排序的問題,爲發現接口IComparableICompare的妙處而興奮,還在公司的內部分享會上分享瞭如何使用它們來排序。如今通過多年的開發實踐以及學習,對於同一個問題又有了更加深刻的理解。html

一. 爲何說」實現了IEnumerable接口才能遍歷」

實習生先是問了這個問題, 其實這個問題, 很是容易解答.
先來看看IEnumerable接口的定義:函數

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

這個接口很是簡單,主要就是一個方法GetEnumerator,用來返回一個IEnumerator對象。
繼續深刻下去,IEnumerator接口的定義以下:學習

public interface IEnumerator
{
   bool MoveNext();
      void Reset();
     object Current {  get; }
}

上面的IEnumerator接口定義的屬性和方法,只有一個目的,就是實現如何遍歷。下面具體解釋一下:spa

  • Current屬性, 用來返回當前集合項的值
  • MoveNext方法, 移動到集合對象的下一項,若是有下一項,就返回true, 若是沒有,就返回false.
  • Reset(), 重置而後能夠重頭訪問集合

到這裏,爲何foreach可以遍歷集合對象的緣由就是由於集合對象都實現了IEnumerable接口,提供了具體的實現來遍歷集合對象。設計

二. Sort()方法以及IComparable、IComparer接口

集合類型,都有Sort()排序方法,這個函數的一個重載版本中,須要提供一個IComparer類型的接口。爲何須要使用這個接口呢?這個和排序有什麼關係?
想想,實現排序必須的是什麼?必須的是可以比較大小。對於int, string這種.Net內部類型,自己已經支持了IComparer, 也就是能夠比較大小了。可是對於咱們本身定義的類型,使用Sort方法是沒法排序的,由於程序不知道咱們對於自定義對象的排序規則, 這個時候就可使用IComparableIComparer.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

image 

2.1 IComparable接口

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

image

2.2 IComparer接口

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屬性不一樣:

image

還能夠實現一個根據Car的屬性Seats排序的IComparer. 因此使用IComparer更加的靈活

3. 面向對象設計思想

Collection中的Sort()方法很好地遵循了開放封閉原則,既很好地完成了排序的功能,同時又開放出了入口,讓你能夠爲排序自定義規則。

下面是我我的的一些我的理解:
一個類應該作本身擅長的事情和核心的事情(單一職責),把不擅長的交給別人。可是這個」別人「是否是任何人均可以呢?固然不是,爲了更好的限定別人,咱們使用了接口限定。
當一個類依賴於抽象(也就是接口),那麼這個類的適用範圍就更加廣,就可以更加超脫。老子一句」道可道,很是道;名可名,很是名」,正是沒有具體化,因此能夠解釋萬物。

更多的面向對象設計原則,參照http://www.360doc.com/content/11/0521/00/3554006_118258005.shtml

最後附上本文相關源代碼: SortDemo

相關文章
相關標籤/搜索