乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Net編程接口剖析系列之比較和排序 (IComparable和IComparer)

       雄Frank 2011-10-23

      我們知道,與C++相比較,C#以及整個.Net并不支持多繼承,而相應(yīng)的,C#支持了接口,并且支持一個類型實現(xiàn)多個接口。對于接口的概念,相信大部分讀者已經(jīng)有了很好的了解,而我這里談?wù)剛€人對于接口理解,只求拋磚引玉。

      在我認(rèn)為,一個接口就是一個對類型的某種能力的認(rèn)證,并且是以某種標(biāo)準(zhǔn)化的形式將這種能力規(guī)范出來。你的類型實現(xiàn)了某個接口,換而言之,也就是說這個類型具備了此接口所標(biāo)識的能力。比如現(xiàn)在出國留學(xué)考托福GRE,開車考駕照這些東西,其實就是相當(dāng)于我們編程中接口;從某種意義上說,你通過了GRE,就說明你具備在國外學(xué)習(xí)所需要的語言能力,而你考取了駕照,就證明了你具有上路行駛的能力了。接口同樣如此,給你類型實現(xiàn)特定的一些接口,就是給他們標(biāo)記了他們所具備的特別能力,而一些依賴這些能力的功能,得以用通用的代碼實現(xiàn)重用,實現(xiàn)可擴展。

      我的這個關(guān)于接口的系列文章,主要是對.Net編程一些非常重要的接口來進行詳細(xì)講解,深入了解這些接口的原理和應(yīng)用。這對于我們寫出精簡優(yōu)美的代碼,是非常有幫助的;畢竟,我們在知道自己想做什么之后,首先應(yīng)該知道.Net Framework能給我們做什么。

      在本篇以及后續(xù)的幾篇文章我們將會談到以下幾個主題:

      (一)比較和排序(IComparable和IComparer)

      (二)枚舉(IEnumerable和IEnumerator)

      (三) 序列化(ISerializable和IXmlSerializable)

      System.IComparable & System.IComparable<T>

      顧名思義,一個實現(xiàn)了IComparable的class應(yīng)該就是一個可以對實例進行相互比較的class,我們先來看看它的定義:

      以下為引用的內(nèi)容:
      [ComVisible(true)]
      public interface IComparable
      {
      int CompareTo(object obj);
      }

      這個接口相當(dāng)簡單,只提供了一個接口函數(shù):CompareTo,如果當(dāng)前對象比被比較的對象小,那么返回負(fù)數(shù);如果相當(dāng),則返回0;如果當(dāng)前對象比被比較的對象大,則返回正數(shù)。

      但是,如果你覺得這個接口僅僅是能夠讓你比較兩個對象大小,那么你就錯了,這個接口更大的作用是能夠?qū)崿F(xiàn)了該類型線性數(shù)據(jù)結(jié)構(gòu)的排序功能。比如List<T>.Sort()和Array的靜態(tài)方法Sort都能夠很好地利用IComparable來對數(shù)據(jù)進行排序,排序算法由類庫實現(xiàn),對于我們來說,只需要讓自己的類型實現(xiàn)IComparable接口,負(fù)責(zé)比較兩個對象大小的算法就可以了。

      IComparable<T>是一個泛型接口,用于實現(xiàn)對特定類型的對象的比較,用法和IComparable基本一致,這里不再進行贅述,下面的例子也是根據(jù)IComparable來寫的。

      我們來看看下面的代碼,這里定義了一個學(xué)生類Student,每個學(xué)生有自己名字和分?jǐn)?shù)。Student類實現(xiàn)了IComparable接口,兩個學(xué)生之間直接按照名字進行比較。順便說明Scores類用于存儲學(xué)生的成績。

      以下為引用的內(nèi)容: public enum SubjectEnum
      {
      Total =0,
      Chinese,
      English,
      Math,
      }
        
      public class Scores //分?jǐn)?shù)類,用于存儲分?jǐn)?shù)
      {
      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 //學(xué)生類
      {
        
      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
      }

      來看看我們的Main函數(shù),我們在一個數(shù)組中存儲了若干個學(xué)生,并且利用了Array.Sort對起進行了排序。

      static void Main(string[] args)
      {
      Student[] students = new Student[4];
      students[0] = new Student("Michale", 80, 90, 70);
      students[1] = new Student("Jack", 90, 80, 75);
      students[2] = new Student("Alex", 88, 85, 95);
      students[3] = new Student("Rose", 92, 91, 65);
        
      Array.Sort(students);
        
      Console.WriteLine("Name  Total  Chinese  English  Math");
      foreach (Student student in students)
      {
      Console.WriteLine(student);
      }
        
      Console.ReadKey();
      }

      下面來看看輸出結(jié)果:

      Name Total Chinese English Math
      Alex  268  88 85  95
      Jack 245 90  80  75
      Michale 240 80 90 70
      Rose 248   92 91 65
       
      可以發(fā)現(xiàn),學(xué)生們被很好的按照名稱字母的順序進行了排序,并且從小到大地打印出來了。但是我們這里還是要留下一個問題,假如我們有時候需要按照某項成績進行排序又如何實現(xiàn)呢?假如我們排序的時候希望按照降序進行排列又該如何呢?呵呵,聰明的讀者可能已經(jīng)想到了,這正是我下一節(jié)想要說的內(nèi)容。

      以下為引用的內(nèi)容: System.Collections.IComparer & System.Collections.Generic. IComparer<T>

      IComparer是這么樣的一個接口,它是用于實現(xiàn)一個專門的“比較器”,這個比較器可以對傳入的兩個對象比較大小。我們來看看它的定義:

      以下為引用的內(nèi)容: [ComVisible(true)]
      public interface IComparer
      {
      int Compare(object x, object y);
      }

      大家可能會對IComparer存在的必要性有點疑問,那就是既然我們有了IComparable就能夠?qū)崿F(xiàn)對象的比較以及排序,那么還需要IComparer做什么呢,豈不是畫蛇添足?我的回答是:不,IComparer的存在很有必要,因為它可以用來實現(xiàn)一些專門的和功能更加強大的比較器。就如現(xiàn)代社會的分工一樣,以前落后的小農(nóng)經(jīng)濟一去不復(fù)返了,社會上的各成員要進行相互協(xié)作才能發(fā)揮最高的效率;同樣,我們設(shè)立專業(yè)的IComparer,使得比較的功能得以擴展和專業(yè)化,你有了更多的選擇。將對象進行比較的時候,你可以使用不同的IComparer來使用不同的方法來比較,就像我們購買商品選擇不同的品牌一樣(試想這件東西不是購買的而是你自己生產(chǎn)的話,那么你就失去了選擇的機會了)。另外專門的IComparer也可以提供一些屬性,來讓我們的比較變得更加靈活。

       

      光說太抽象,我們下面還是繼續(xù)上一節(jié)對學(xué)生進行排序的問題進行討論。這里我們可以創(chuàng)建一個專門的學(xué)生比較類StudentComparer, 而它則實現(xiàn)了IComparer的泛型接口System.Collections.Generic.IComparer<Student>,StudentComparer的作用是根據(jù)成績對學(xué)生進行比較。為了將IComparer的優(yōu)越性體現(xiàn)出來,我們這里在StudentComparer的構(gòu)造函數(shù)中增加了兩個參數(shù)subject和reverse,前者用于指定我們要按照何種科目成績進行比較,而后者則指定是否將結(jié)果取反(當(dāng)然我們也可以使用Array.Reverse方法來將結(jié)果按照降序排列,這里只是實現(xiàn)方法之一)。好,這樣我們比較器就這樣設(shè)計好了,看看下面的代碼:

      以下為引用的內(nèi)容: public class StudentComparer: System.Collections.Generic.IComparer<Student>
      {
      SubjectEnum _subject;
      bool _reverse;
        
      public StudentComparer(SubjectEnum subject, bool reverse)
      {
      _subject = subject;
      _reverse = reverse;
      }
        
      #region IComparer<Student> Members
        
      public int Compare(Student left, Student right)
      {
      if (left == null && right == null)
      return 0;
      else if (left == null)
      return -1;
      else if (right == null)
      return 1;
        
      //比較響應(yīng)科目的成績
      int result = left.Scores[_subject].CompareTo(right.Scores[_subject]);
        
      //如果反序,只要將結(jié)果取反即可
      if (_reverse) result = -result;
      return result;
      }
       
      #endregion
      }

      一個功能強大的比較器就這樣實現(xiàn)了,那么接下來我們就來實現(xiàn)將學(xué)生按照總分進行從高到底的排序,這里我們只需要對main函數(shù)進行稍微的修改就可以了,使用Array.Sort的另外一個重載方法Array.Sort (T[], Generic IComparer) 來進行比較。

      看到上面我們在StudentComparer的構(gòu)造函數(shù)中傳入了Total(總分)和True(降序),我們看看執(zhí)行結(jié)果:

      Name Total Chinese English Math
      Alex  268    88  85  95
      Rose  248 92 91 65
      Jack  245 90 80 75
      Michale 240 80      90 70

      太棒了,IComparer是這樣的神奇,想象一下如果沒有IComparer而僅僅要用IComparable來實現(xiàn)上面的功能,將是多么麻煩的事情,更加重要的是,那會將Student類的代碼變的一團糟,就如同一個上班族卻天天要想著回家給自己種的蔬菜澆澆水,給自己養(yǎng)的豬喂喂食一樣,這些瑣碎的東西會讓你的生活一團糟的。

      .Net的庫類的排序功能是如此強大,以至于我們還能夠利用代理來進行排序(其實是將比較功能寫在自己的專門函數(shù)中),但是本文的重點是講解接口,所以這里對利用代理排序不再詳述,只是提一下而已。

      我們從IComparable和IComparer上學(xué)到的,應(yīng)當(dāng)不僅僅是比較和排序,而更加應(yīng)該學(xué)到一種思路,一種設(shè)計模式,這才是最重要的;另外,它們還有助于加深我們對接口的理解。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多