程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 第11章 集合、比較和轉換(C#入門經典第6版),

第11章 集合、比較和轉換(C#入門經典第6版),

編輯:C#入門知識

第11章 集合、比較和轉換(C#入門經典第6版),


1、集合

      數據有一定的限制,最不能忍受的是一旦創建,數組的大小就固定,不能再添加。而集合則包含了數組所具有的功能,且可以任意添加/刪減元素項,還有一些其他 功能。

  集合的功能主要通過接口來實現,接口包含在System.Collections命名空間中。

  主要有:

  • IEnumerable 可以迭代集合中的元素項
  • ICollection(繼承於IEnumerable)可以獲得集合中元素項的個數,並能把元素項復制到一個簡單的數組類型中。
  • IList(繼承於IEnumerable和ICollection)提供了集合的元素項列表,允許訪問這些項,並提供其他一些與元素項列表相關的基本功能。
  • IDictionary(繼承於IEnumerable和ICollection)類似於IList,但提供了可通過健值訪問的元素項列表。

     (1)System.Array類與System.Collections.ArrayList類

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Console.WriteLine("Create an Array type collection of Animal " +
 6                 "objects and use it:");
 7             Animal[] animalArray = new Animal[2];
 8             Cow myCow1 = new Cow("Deirdre");
 9             animalArray[0] = myCow1;
10             animalArray[1] = new Chicken("Ken");
11 
12             foreach (Animal myAnimal in animalArray)
13             {
14                 Console.WriteLine("New {0} object added to Array collection, " +
15                     "Name = {1}", myAnimal.ToString(), myAnimal.Name);
16             }
17 
18             Console.WriteLine("Array collection contains {0} objects.", animalArray.Length);
19             animalArray[0].Feed();
20             ((Chicken)animalArray[1]).LayEgg();
21             Console.WriteLine();
22 
23             Console.WriteLine("Create an ArrayList type collection of Animal " +
24                 "objects and use it:");
25             ArrayList animalArrayList = new ArrayList();
26             Cow myCow2 = new Cow("Hayley");
27             animalArrayList.Add(myCow2);
28             animalArrayList.Add(new Chicken("Roy"));
29 
30             foreach (Animal myAnimal in animalArrayList)
31             {
32                 Console.WriteLine("New {0} object added to ArrayList collection," +
33                     " Name = {1}", myAnimal.ToString(), myAnimal.Name);
34             }
35             Console.WriteLine("ArrayList collection contains {0} objects.", animalArrayList.Count);
36             ((Animal)animalArrayList[0]).Feed();
37             ((Chicken)animalArrayList[1]).LayEgg();
38             Console.WriteLine();
39 
40             Console.WriteLine("Additional manipulation of ArrayList:");
41             animalArrayList.RemoveAt(0);
42             ((Animal)animalArrayList[0]).Feed();
43             animalArrayList.AddRange(animalArray);
44             ((Chicken)animalArrayList[2]).LayEgg();
45             Console.WriteLine("The animal called {0} is at index {1}.",
46                 myCow1.Name, animalArrayList.IndexOf(myCow1));
47             myCow1.Name = "Janice";
48             Console.WriteLine("The animal is now called {0}.",
49                 ((Animal)animalArrayList[1]).Name);
50             Console.ReadKey();
51         }
52     }

  System.Array類只能在初始化時固定數組大小,如:

  Animal[] animalArray = new Animal[2];

  而System.Collections.ArrayList類則是:

  ArrayList animalArrayList = new ArrayList();//可以設置容量 ,但當超過時會自動增加一倍。

簡單數組Array中是強類型的,本例中是Animal類型,而ArrayList中則是System.Object。

System.Array類和ArrayList都實現了IEnumerable接口,因此可以在foreach中迭代。

 (2)定義集合---創建自己的強類型化集合

  一般情況是從一個類中派生自己的集合,例如System.Collections.CollectionBase類,這個抽象類提供了集合類的大量的實現代碼,包含了IEnumerable、ICollection、Ilist接口。

  CollectionBase類提供了兩個受保護的屬性,可以訪問存儲對象本身。List可以通過IList接口訪問項,而InnerList則可用於存儲項的ArrayList對象。

 1 public class Animals:CollectionBase
 2     {
 3         public void Add(Animal newAnimal)
 4         {
 5             List.Add(newAnimal);
 6         }
 7         public void Remove(Animal oldAnimal)
 8         {
 9             List.Remove(oldAnimal);
10         }
11         public Animals()
12         {
13 
14         }
15     }

(3)索引符

  上面定義的集合Animals是不能如animalCollection[0].Feed()這樣按照索引來訪問元素項的,必須使用索引符。

  索引符其實是一種特殊類型的屬性,可添加在類中,提供類似於數組的訪問。

1  public Animal this[int animalIndex]//this關鍵字和後邊的方括號中的參數一起使用,如MyAnimals[0]。
2         {
3             get { return (Animal)List[animalIndex]; }
4             set { List[animalIndex] = value; }
5         }
 

小結:通過使用CollectionBase創建自己的強類型化集合集中了System.Array類的強類型化和System.Collections.ArrayList的多種項列表操作方法的優點,比較方便。但是內部還是發生了類型轉換。

(4)鍵控集合和IDictionary

  類似於IList接口通過數字索引訪問項列表,IDictionary接口通過健值進行索引。同樣,也有一個基類實現了IDictionary接口,DictionaryBase。

  

 1 public class Animals:DictionaryBase
 2     {
 3         public void Add(string newID,Animal newAnimal)
 4         {
 5             Dictionary.Add(newID, newAnimal);
 6         }
 7         public void Remove(string animalID)
 8         {
 9             Dictionary.Remove(animalID);
10         }
11         public Animals()
12         { }
13 
14         public Animal this[string animalID]
15         {
16             get { return (Animal)Dictionary[animalID]; }
17             set { Dictionary[animalID] = value; }
18         }
19     }

  但是基於DictionaryBase的集合和基於CollectionBase的集合之間還有一個區別是foreach的工作方式稍有區別。基於CollectionBase的集合可以從集合中直接提取Animal對象,而使用foreach和DictionaryBase的集合則需要提供DictionaryEntry結構才能得到類似的效果。

  

1             foreach (DictionaryEntry myEntry in animalCollection)
2             {
3                 Console.WriteLine("New {0} object added to custom collection, " +
4                     "Name = {1}", myEntry.Value.ToString(), ((Animal)myEntry.Value).Name);
5             }

(5) 迭代器

  迭代器的定義是,它是一個代碼塊,按順序提供了要在foreach循環中使用的所有值。迭代器代碼塊的返回類型有兩種,IEnumerable和IEnumerator。

如果要迭代一個類,可使用方法GetEnumerator(),其返回類型是IEnumerator。

如果要迭代一個類成員,則使用IEnumerable。

  這裡要使用yield關鍵字,但書上沒有詳細介紹。

(6)深度復制

  所謂深度復制和淺度復制,在值類型上感覺是沒有區別的,都是復制一個值,而在引用類型上,淺度復制是復制對象的一個相同的引用,副本改變後則源也要改變。但是深度復制則不同,其復制對象的內容(包括字段等)而引用不同,副本發生變化時,源則不變。

 

2、比較

(1)類型比較

  a. 封箱與拆箱

  封箱是把值類型轉換為System.Object類型或者轉換為由值類型實現的接口類型。包含值類型變量的一個副本的引用。

  拆箱是相反的過程。

  封箱是在沒有用戶干涉的情況下進行的(即不需要編寫任何代碼),但是拆箱一個值需要進行顯式轉換,即需要類型轉換。

  b. is運算符

  is運算符並不是用來說明對象是某種類型,而是用來檢查對象是不是給定類型,或者是否可以轉換為給定類型,如果是,就返回true。

  <operand> is <type>

  •  如果<type>是一個類類型,而<operand>也是該類型,或者它繼承了該類型,或者它可以封裝到該類型中,則結果為true。
  •    如果<type>是一個接口類型,而<operand>也是該類型,或者它是實現該接口的類型,則結果為true。
  •    如果<type>是一個值類型,而<operand>也是該類型,或者它可以拆箱到該類型中,則結果為true。

(2)值比較

  a. 運算符重載

  要在類中重載運算符,必須給類添加運算符類型成員(使用operator關鍵字和運算符本身)且必須是static。

  b. 使用IComparable和IComparer接口,該種方式廣泛用於集合類中。

  • IComparable在要比較的對象的類中實現,可以比較該對象和另一個對象
  • IComparer在一個單獨的類中實現,可以比較任意兩個對象

  一般使用IComparable給出類的默認比較代碼,使用其他類給出非默認的比較代碼。IComparable提供了一個方法CompareTo(),這個方法接受一個對象。IComparer也提供了一個Compare()方法。

  最後,.Net Framework在類Comparer上提供了IComparer接口的默認實現方式,類Comparer位於System.Collections命名空間中,可以對簡單類型以及支持IComparable接口的任意類型進行特定文化的比較。

3、轉換

(1)重載轉換運算符

  在代碼中,使用關鍵字implicit和explicit來指定轉換

 1     public class ConvClass1
 2     {
 3         public int val;
 4         public static implicit operator ConvClass2(ConvClass1 op1)
 5         {
 6             ConvClass2 returnVal = new ConvClass2();
 7             returnVal.val = op1.val;
 8             return returnVal;
 9         }
10 
11     }
12     public class ConvClass2
13     {
14         public double val;
15         public static explicit operator ConvClass1(ConvClass2 op1)
16         {
17             ConvClass1 returnVal = new ConvClass1();
18             returnVal.val = (int)(op1.val);
19             return returnVal;
20         }
21     }

 

(2) as運算符

  使用下面的語法,把一種類型轉換為指定的引用類型。

  <operand> as <type>

  •  <operand>的類型是<type>類型
  •   <operand>可以隱式轉換為<type>類型
  •    <operand>可以封箱到<type>類型中

  如果不能從<operand>轉換為<type>,則表達式的結果為null。

   

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved