C#快速入門教程(22)—— 常用集合型別

曹化宇發表於2018-11-02

關於資料集合的處理,前面已經討論過陣列的使用,主要使用了Array類,使用Array物件時,首先會確定成員數量,需要改變成員數量時,就會建立一個新的Array物件,這樣一來,動態處理陣列的效率是比較低的;不過,在.NET Framework類庫中還提供了不少用於處理集合的資源,它們主要定義在兩個名稱空間,即:

  • System.Collections名稱空間,定義集合處理的非泛型型別。
  • System.Collections.Generic名稱空間,定義集合處理的泛型型別。

接下來將介紹兩組集合處理的型別,分別是ArrayList類和List泛型類,Hashtable類和Dictionary泛型類,請注意它們定義的名稱空間,並在程式碼檔案中正確引用。

ArrayList類與List泛型類

ArrayList類和List泛型類用於處理有序的集合,成員使用從0開始的索引值進行訪問。下面的程式碼,我們先來看ArrayList類的基本應用。

static void Main(string[] args)
{
        ArrayList arr = new ArrayList();
        arr.Add("aaa");
        arr.Add(123);
        arr.Add(true);
        arr.Insert(0, DateTime.Now);
        //
        foreach(object obj in arr)
        {
            Console.WriteLine(obj.ToString());
        }
}

本例中,首先定義了ArrayList型別的arr物件,使用Add()方法新增了三個成員,然後使用Insert()方法將系統的當前時間新增到索引值為0的位置(即第一個成員);最後,使用foreach語句顯示所有的成員。程式碼執行結果如下圖所示(你的執行結果應該只有第一個成員的時間不一樣)。

enter image description here

這裡,我們可以看到ArrayList類的一些特點,最主要的是其成員型別是Object型別的,也就是說,可以將任何型別新增到ArrayList物件的成員中,這樣可以有最大的靈活性,但問題也同樣突出,即在集合中同時處理多種資料型別時,型別的轉換是需要時間的,這就給程式碼的執行效率帶來了負面影響;而List泛型類就可以解決部分問題,當集合成員的資料型別相同時,就可以使用List類來提高程式碼的執行效率,如下面的程式碼。

static void Main(string[] args)
{
        List<string> lst = new List<string>();
        lst.Add("aaa");
        lst.Add("bbb");
        lst.Add("ccc");
        //
        for (int i = 0; i < lst.Count; i++)
        {
            Console.WriteLine(lst[i]);
        }
}

程式碼執行結果如下圖所示。

enter image description here

實際應用中,ArrayList和List類有很多相似之處,包括相同的成員名,如Add()、Insert()、Remove()等方法,Count等屬性,以及從0開始的索引值等等。只是需要注意一點,ArrayList物件的成員型別是Object,靈活儲存各種型別的資料時,有時會需要型別轉換工作,而List物件中的成員型別是相同的,這樣就可以更直接地處理(效率更高);區分它們之間的不同,才可以在程式碼中合理地選擇應用。

Hashtable類和Dictionary泛型類

Hashtable類和Dictionary泛型類,用於處理“鍵/值”對應的資料型別,即在集合中,每一個鍵(Key)對應一個值(Value),可以使用鍵來訪問相應的資料值。下面是Hashtable類的基本應用方式。

static void Main(string[] args)
{
        Hashtable hash = new Hashtable();
        hash.Add("Earth", "地球");
        hash.Add("Mars", "火星");
        Console.WriteLine(hash["Mars"]);
}

這裡,使用hash["Mars"]訪問hash物件中鍵為Mars的資料,程式碼會顯示“火星”。

Hashtable的鍵、值都定義為Object型別,這樣也就帶來了最大的靈活性,和ArrayList的問題一樣,當使用不同型別的資料時,可能需要型別的轉換工作;而Dictionary泛型類則可以繫結鍵和值的型別,如下面的程式碼。

static void Main(string[] args)
{
        Dictionary<string, string> dict = new Dictionary<string, string>();
        dict.Add("Earth", "地球");
        dict.Add("Mars", "火星");
        Console.WriteLine(dict["Mars"]);
}

程式碼執行同樣會顯示“火星”。

使用Hashtable和Dictionary類時還應該注意,鍵的內容是區分大小寫的,即mars和Mars表示不同的資料項,如果使用了不存在的鍵,則返回一個空值。另一方面,在使用這兩個類時,不應假設成員的順序,而只是使用指定的鍵來返回資料值,需要訪問所有成員時,可以使用foreach語句結構遍歷所有的鍵進行操作,如下面的程式碼。

    static void Main(string[] args)
    {
        Dictionary<string, string> dict = new Dictionary<string, string>();
        dict.Add("Earth", "地球");
        dict.Add("Mars", "火星");
        //
        foreach(string k in dict.Keys)
        {
            Console.WriteLine("{0} : {1}", k, dict[k]);
        }
    }

本例中,Dictionary物件的Keys屬性返回了所有鍵的集合,並通過foreach語句結構遍歷所有鍵顯示相應的資料值,程式碼執行結果如下圖所示。

enter image description here

以上,我們瞭解了常用的集合型別,包含使用從0開始索引的“有序”集合ArrayList類和List泛型類,以及使用鍵索引的“無序”集合Hashtable類和Dictionary泛型類;大家可以根據這些集合類的特點合理應用到自己的程式碼中。

綜合應用

實際應用中,可以根據實際需要擴充套件集合類的使用,如下面的程式碼。

using System.Collections.Generic;

namespace ConsoleTest
{
    //
    public class CDataItem
    {
        //
        public CDataItem(string sName, object oValue)
        {
            Name = sName;
            Value = oValue;
        }
        //
        public string Name { get; set; }
        public object Value { get; set; }
    }
    //
    public class CDataList : List<CDataItem>
    {

    }
}

本例,首先定義了CDataItem類,其中包含兩個屬性,分別是Name屬性(string型別)和Value屬性(object型別);然後,定義了CDataList類,其繼承於List型別,也就是說,列表的成員型別是CDataItem物件;接下來,CDataList型別包含了列表基本操作,並可以根據需要建立自己的操作方法。這裡定義的CDataList類,即可以保持成員的有序性,也可以根據資料的名稱進行相應的操作,如下面的程式碼,我們可以在CDataList類中定義一個Find()方法,用於查詢指定名稱的資料項,並返回其索引值,沒有找到時返回-1。

public class CDataList : List<CDataItem>
{
    public int Find(string sName)
    {
        for(int i=0;i<Count;i++)
        {
            if (string.Compare(sName, this[i].Name, false) == 0)
                return i;
        }
        return -1;
    }
}

下面的程式碼演示了Find()方法的使用。

static void Main(string[] args)
{
        CDataList lst = new CDataList();
        lst.Add(new CDataItem("Earth", "地球"));
        lst.Add(new CDataItem("Mars", "火星"));
        //
        Console.WriteLine(lst.Find("Mars"));
        Console.WriteLine(lst.Find("Moon"));
}

程式碼執行結果如下圖所示。

enter image description here

CHY軟體小屋原創作品!

相關文章