C#入門經典 -- 11.1 集合

來源:互聯網
上載者:User

    C#中的數組實現為System.Array類的執行個體,它們只是集合類中的一種。集合類一般用於處理對象列表,其功能比簡單數組要多,這些功能是通過實現System.Collections命名空間中的介面而獲得的,因此介面的文法已經標準化了。

    集合的功能(包括基本函數,例如用[index]文法訪問集合中的項。)可以通過介面來實現,該介面不僅沒有限制我們使用基本集合類,例如System.Array,相反,我們還可以建立自己的定製集合類。這些集合可以專用於要枚舉的對象(即要從中建立集合的對象)。這麼做的一個優點是定製的集合類可以是強型別化的。也就是說,從集合中提取項時,不需要把它們轉換為正確的類型。另一個優點是提供專門的方法,例如,可以提供獲得項子集的快捷方法。

    在System.Collections命名空間中有許多介面都提供了基本的集合功能:

  • IEnumerable可以迭代集合中的項。
  • ICollection(繼承於IEnumerable)可以擷取集合中項的個數,並能把項複製到一個簡單的數群組類型中。
  • IList(繼承於ICollection)提供了集合的項列表,並可以訪問這些項,以及其他一些與項列表相關的功能。
  • IDictionary(繼承於ICollection)類似於IList,但提供了可通過鍵碼值而不是索引訪問的項列表。

    System.Array類實現了IList、ICollection和IEnumerable,但不支援IList的一些更進階的功能,表示大小固定的項列表。

11.1.1 使用集合

    System.Collections命名空間中的一個類System.Collections.ArrayList也實現了IList、ICollection和IEnumerable介面,但實現的方式比System.Array更複雜。

【樣本】

   類Animal

   1:  namespace Ch11Ex01
   2:  {
   3:      class Animal
   4:      {
   5:          protected string name;
   6:   
   7:          public string Name
   8:          {
   9:              get
  10:              {
  11:                  return name;
  12:              }
  13:              set
  14:              {
  15:                  name = value;
  16:              }
  17:          }
  18:   
  19:          public Animal()
  20:          {
  21:              name = "The animal with no name";
  22:          }
  23:   
  24:          public Animal(string newName)
  25:          {
  26:              name = newName;
  27:          }
  28:   
  29:          public void Feed()
  30:          {
  31:              Console.WriteLine("{0} has been feed.",name);
  32:          }
  33:      }
  34:  }
 


類Cow
   1:  namespace Ch11Ex01

   2:  {

   3:      class Cow:Animal

   4:      {

   5:          public void Milk()

   6:          {

   7:              Console.WriteLine("{0} has ben milked.",name);

   8:          }

   9:   

  10:          public Cow(string name)

  11:              : base(name)

  12:          { 

  13:   

  14:          }

  15:      }

  16:  }

 

類Chicken

   1:  class Chicken: Animal
   2:      {
   3:          public void LayEgg()
   4:          {
   5:              Console.WriteLine("{0} has laid an egg.",name);
   6:          }
   7:   
   8:          public Chicken(string name):base(name)
   9:          {
  10:   
  11:          }
  12:      }

 Program代碼:
class Program    {        static void Main(string[] args)        {            Console.WriteLine("Create an Array type collection of Animal objects and use it.");            Animal[] animalArray = new Animal[2];            Cow myCow1 = new Cow("Deirdre");            animalArray[0] = myCow1;            animalArray[1] = new Chicken("Ken");            foreach (Animal myAnimal in animalArray)            {                Console.WriteLine("New {0} object added to Array collection,Name = {1}",myAnimal.ToString(),myAnimal.Name);            }            Console.WriteLine("Array collection contains {0} objects.",animalArray.Length);            animalArray[0].Feed();            ((Chicken)animalArray[1]).LayEgg();            Console.WriteLine();            Console.WriteLine("Create an ArrayList type collection of Animal objects and use it.");            ArrayList animalArrayList = new ArrayList();            animalArrayList.Add(new Cow("Hayley"));            animalArrayList.Add(new Chicken("Rory"));            foreach (Animal myAnimal in animalArrayList)            {                Console.WriteLine("New {0} object added to Array collection,Name = {1}",myAnimal.ToString(),myAnimal.Name);            }            ((Cow)animalArrayList[0]).Feed();            ((Chicken)animalArrayList[1]).LayEgg();            Console.WriteLine();            Console.WriteLine("Addition manipulation of ArrayList:");            animalArrayList.RemoveAt(0);            ((Animal)animalArrayList[0]).Feed();            animalArrayList.AddRange(animalArray);            ((Chicken)animalArrayList[2]).LayEgg();            Console.WriteLine("The animal called {0} is at index {1}",myCow1.Name,animalArrayList.IndexOf(myCow1));            myCow1.Name = "Janice";            Console.WriteLine("The animal is now called {0}",((Animal)animalArrayList[1]).Name);            Console.ReadKey();        }    }
 運行結果如下:
 
   
 
【樣本說明】
    這個樣本建立了兩個對象集合,第一個集合使用System.Array(這是一個簡單的數組),第二個集合使用
System.Collections.ArrayList類。這兩個集合都是Animal對象,在Animal.cs中定義。Animal類是抽象類別,所以不能進行
執行個體化。但通過多態性,可以使用集合中項成為派生於Animall類的Cow和Chicken類執行個體。
    下面首先通過比較這兩種集合的代碼和結果,討論一下這兩種集合的類似操作。
    首先是集合的建立。對於簡單的數組來說,必須用固定的大小來初始化數組,才能使用它。
         Animal[] animalArray = new Animal[2];
    而ArrayList集合不需要初始化其大小,所以可以使用下面的代碼建立列表anmialArrayList:
         ArrayList animalArrayList = new ArrayList();

       這個類還有另外兩個建構函式。第一個建構函式把現有的集合作為一個參數,把現有集合的內容複寫到新執行個體中;而另一個建構函式通過一個參數設定集合的容量(capactiy)。這個容量用一個int值指定,設定集合中可以包含的項數。但是這並不是真實的容量,因為如果集合中的項數超過了這個值,容量就會自動增大一倍。

    因為數組是參考型別的,所以用一個長度初始化數組並沒有初始化它所包含的項。要使用一個指定的項,該項還需要初始化,即需要給這個項賦予初始化了的對象:

                    Cow myCow1 = new Cow("Deirdre");

           animalArray[0] = myCow1;

           animalArray[1] = new Chicken("Ken");

    這段代碼以兩種方式完成該初始化任務:用現有的Cow對象來賦值,或者通過建立一個新的Chicken對象來賦值。主要區別是前者引用了數組中的對象。

    對於ArrayList集合,它沒有現成的項,也沒有null引用的項。這樣就不能以相同的方式給索引賦予新執行個體。我們使用ArrayList對象的Add()方法添加新項:

        Cow myCow2 = new Cow("Hayley");

       animalArrayList.Add(myCow2);

    animalArrayList.Add(new Chicken("Rory"));

   除了文法略有不同外,還可以用相同的方式把新對象或現有的對象添加到集合中。

   以這種方式添加完項後,就可以使用與數組相同的文法來重寫它們,例如:

      animalArrayList[0] = new Cow("Alma");

   可以使用foreach結構迭代一個數組,因為System.Array類實現了IEnumerable介面,這個介面的唯一方法GetEnumerator()可以迭代集合中的項目。在代碼中,我們寫出了數組中的每個Animal對象的資訊:

           foreach (Animal myAnimal in animalArray)

       {

            Console.WriteLine("New {0} object added to Array collection,Name = {1}",myAnimal.ToString(),

                    myAnimal.Name);

       }

    這裡使用的ArrayList對象也支援IEumerable介面;並可以與foreach一起使用,此時文法是相同的。

       foreach (Animal myAnimal in animalArrayList)

      {

         Console.WriteLine("New {0} object added to Array collection,Name = {1}",myAnimal.ToString(),

                  myAnimal.Name);

      }

    接著,使用數組的Length屬性,在螢幕上輸出數組中項的個數:

       Console.WriteLine("Array collection contains {0} objects.",animalArray.Length);

    也可以使用ArrayList集合得到相同的結果,但要使用Count屬性,該屬性是ICollection介面的一部分:

      Console.WriteLine("ArrayList collection contains {0} objects.",animalArrayList.Count);

    簡單數組是強型別化的,可以直接存取它們所包含的項類型。所以可以直接調用項的方法:

      animalArray[0].Feed();

    數組的類型是抽象類別型Animal,因此不能直接調用有衍生類別提供的方法,而必須使用資料類型轉換:

     ((Chicken)animalArray[1]).LayEgg();

    ArrayList集合是System.Object對象的集合(通過多態性賦給Animal對象),所以必須對所有的項進行資料類型轉換:

      ((Animal)animalArrayList[0]).Feed();

      ((Chicken)animalArrayList[1]).LayEgg();

    代碼的剩餘部分利用的一些ArrayList集合功能超出了Array集合的功能範圍。

    首先,可以使用Remove()和RemoveAt()方法刪除項,這兩個方法是在ArrayList類中實現的IList介面的一部分。它們分別根據項目引用或索引把項目從數組中刪除。在本例中,我們使用後一個方法刪除添加在到列表中的第一個項,即Name屬性為Hayley的Cow對象:

      animalArrayList.RemoveAt(0);

    另外,還可以使用:

      animalArrayList.Remove(myCow2);

    無論採用哪種方式,集合中唯一剩下的項是Chicken對象,可以用下面的方式訪問它:

      ((Animal)animalArrayList[0]).Feed();

    對ArrayList對象中的項進行修改,使數組中剩下N個項,其實現方式與保留0~N-1的索引相同。例如,刪除索引為0的項,會使其他項在數組中移動一個位置,所以應使用索引0來訪問Chicken對象,而不是1。不再有索引為1的項了(因為集合中最初只有兩個項),所以如果試圖執行下面的代碼,就會拋出異常:

      ((Animal)animalArrayList[1]).Feed();

    ArrayList集合可以用AddRange()方法一次添加好幾個項。這個方法接受帶有ICollection介面的任何對象,該介面包含前面的代碼所建立的animalArray數組:

      animalArrayList.AddRange(animalArray);

    AddRange()方法不是ArrayList提供的任何介面的一部分。這個方法專用於ArrayList類,論證了可以在集合類中執行定製操作,而不僅僅是前面介紹的介面要求的操作。這個類還提供了其他有趣的方法,例如InsterRange(),它可以把數組對象插入到列表中的任何位置,還有用於給數組排序和重新排序的方法。

    最後,再回頭來看看對同一個對象進行多個引用。使用IList介面中的IndexOf()方法可以看出,myCow1(最初添加到animalArray中的一個對象)現在是animalArrayList集合中的一部分,它的索引如下:

      Console.WriteLine("The animal called {0} is at index {1}.",myCow1.Name,animalArrayList.IndexOf(myCow1));

    例如,接下來的兩行代碼通過對象引用重新命名了對象,並通過集合引用顯示了新名稱:

      myCow1.Name = "Janice";

      Console.WriteLine("The animal is now called {0}.",((Animal)animalArrayList[1].Name));

   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.