泛型是C#2.0搭配.NET Framework 2.0推出的東西,泛型是一種模板,將型別傳入模板,讓我們產生對應型別的類別、方法或變數等等,減少只是因為型別不同而重複的程式碼。另外.NET Framework 2.0推出的泛型集合List<T>
類別,可以讓我們快速製作自訂類別的集合,減少C#1.0自訂類別集合製作方式的效能問題與除錯困難的問題。今天會講ArrayList與List<T>,明天講泛型。
集合(Collections)是一群不確定數量的類別聚集起來稱為集合,相對地如果是一群確定數量的類別那稱為陣列(array),一個集合物件裡面類別物件數量可以增加或減少,一個陣列物件裡面的類別數量在new出來就已經決定。
例如:報名人數列表,我們可能就會用集合來作而不是陣列,畢竟陣列建立出來後就是固定大小固定數量的,如果一張表上陣列格數20格,當報名人數超過20人時,陣列的作法是拿新的表劃出30格或40格陣列,再把舊表的20格複製到新表上去,其實很麻煩也有記憶體上的效能問題。這種例子改用集合作就非常好,可以動態的增加格子數,也不用重新產生新的表。
.NET Framework1.0最早在命名空間System.Collections中提供多種集合類別,並於2.0時新增System.Collections.Generic命名空間提供多種實用非常多的泛型集合。
我們自訂的類別要做集合,在C# 1.0我們會用.NET類別庫的ArrayList來作,使用上比較繁瑣外,問題還很多。當2.0出現泛型集合List<T>之後,C#工程師就像是獲得救贖。(所以現在不要再用ArrayList)
。
我們說C#中所有東西都是物件、都是繼承自System.Object,所以如果要作不確定數量的物件集合,ArrayList都把所由類別物件都轉型成object存起來,在取出時才轉型成我們要得類別物件。除了存取上頻繁的轉型耗能外,執行時轉型錯誤的情況常常不是編譯器能事前發現的。
例如我們有一個會員列表,程式碼如下:
public class 會員
{
public string 會員ID { get; set; }
public string 名稱 { get; set; }
}
如果寫錯轉型的型別,C#編譯器檢查時並不會發現,如果集合中物件數量很多,便會每次多取都要進行轉型而降低效能。如果怕每次操作這個會員列表時都要寫一次轉型,可以是用先前講的索引函式,如下:
public class 會員名冊
{
private ArrayList 名冊 = new ArrayList();
public void Add(會員 人)
{
名冊.Add(人);
}
public 會員 this [int index]
{
get
{
if (index >= 0 && index < 名冊.Count)
{
return (會員)名冊[index];
}
else
{
return null;
}
}
set
{
if (index >= 0 && index < 名冊.Count)
{
名冊[index] = value;
}
if(index == 名冊.Count)
{
名冊.Add(value);
}
}
}
}
可以看到我們的會員人會轉成object
使用時就不用再寫轉型型別:
但這樣寫起來很麻煩,而且該天若要作員工名冊、廠商名冊等相似的內容,不是要一值複製貼上嗎?如果要更改名冊的程式碼不就要一個一個找?在C#2.0List<T>出現了。
List<T>是.NET Framework2類別庫提供的泛型集合,將<>號裡面的T改成我們指定的型別,就會產生對應型別的集合,存入取出的過程都會是我們指定的型別,而不用每次都轉換成object影響到效能,編譯器也會知道我們指定成什麼型別,幫我們正確的進行型別檢查,免得執行時才發現選錯型別。另外透過List<T>這一份模板可以幫我們省略掉剛剛撰寫ArrayList索引函式,也不用因為員工名冊、廠商名冊的出現而複製成多份的程式碼。
透過替換其他型別,就能產生對於廠商、員工的程式碼。快速又簡單。