System.Collections常用集合使用範例
System.Collections應該是所有程式設計師最常使用的namespace了吧,對我來說,常常是心之所至想到什麼就寫什麼,反正可以用就好了。不幸的是上次踩到了一個執行期的地雷(在具備Hash Index的集合中,加入重複的鍵值),所以只好把所知道的集合整了一下,提醒自己以後不要再犯這種陽春等級的錯誤。
程式碼如下所示,哪些可以重複鍵值(非雜湊集合),哪些不可以重複鍵值(雜湊集合),請務必自己要搞清楚喔!
static void Main(string[] args)
{
//////////
//非雜湊集合
//////////
System.Collections.ArrayList oAL = new System.Collections.ArrayList();
oAL.Add("John");
oAL.Add("John"); //OK
System.Collections.Generic.List<string> oIL = new System.Collections.Generic.List<string>();
oIL.Add("John");
oIL.Add("John"); //OK
System.Collections.Generic.IEnumerable<string> oIE = new string[] { "John", "John" };
//////////
//雜湊集合
//////////
System.Collections.Hashtable oHT = new System.Collections.Hashtable();
oHT.Add("John", "1234");
//oHT.Add("John", "1234"); //Error
foreach (System.Collections.DictionaryEntry oItem in oHT)
{
WriteLine($"Hashtable | key:{oItem.Key.ToString()}, value:{oItem.Value.ToString()}");
}
System.Collections.Generic.Dictionary<string, string> oDI = new System.Collections.Generic.Dictionary<string, string>();
oDI.Add("John", "1234");
//oDI.Add("John", "1234"); //Error
foreach (System.Collections.Generic.KeyValuePair<string, string> oItem in oDI)
{
WriteLine($"Dictionary | key:{oItem.Key.ToString()}, value:{oItem.Value.ToString()}");
}
}
在兩個雜湊集合(Hashtable、Dictionary)中,我加入了foreach的寫法將其讀出,可能會有人認為幹嘛寫成這麼複雜,用var動態型別不就好了?我會這樣寫的原因,是因為要提醒我自己這邊的子屬類別是什麼,純粹是「多知道一件事就少犯下一件錯」。而一般來說,Hashtable、Dictionary不太有人會進行foreach的操作,因為類別中提供的ContainsKey、ContainsValue等方法成員就已經很好用了。
至於IEnumerable是所有泛型集合的根源,它實質上只是一個指標指往欲存取的目標實體(instance)而已,我通常用佐以yield return,來解決陣列型別無法動態的新增資料的問題。範例程式碼如下:
利用IEnumerable讓傳統的物件陣列,也可以動態的新增資料
public class Person
{
public string cName { set; get; }
}
class Program
{
static void Main(string[] args)
{
Person[] oPers = new Person[]
{
new Person() { cName = "123" },
new Person() { cName = "456" }
};
System.Collections.Generic.IEnumerable<Person> oTemp;
oTemp = AddPerson(oPers, new Person() { cName = "789" });
oTemp = AddPerson(oTemp, new Person() { cName = "012" });
foreach (var item in oTemp)
{
WriteLine(item.cName);
}
}
static System.Collections.Generic.IEnumerable<Person> AddPerson(System.Collections.Generic.IEnumerable<Person> oSource, Person oTarget)
{
foreach (Person item in oSource) { yield return item; }
yield return oTarget;
}
}
執行結果當然就是:
123
456
789
012
補充說明:
- 對IEnumerable有興趣的人,可以參考我的另外一篇文章: 利用yield return與IEnumerable(T)來讓ORM類別可以被集合化與尋訪
- 對System.Collections.Specialized有興趣的人,可以參考我的另外一篇文章: 利用.NET Collections類別來幫你達成Group的功能
- 另有一篇MS MVP Huan-Lin以其他的的面向去整理的集合類型,同樣非常具有參考價值: 選擇合適的 .NET 集合類型