在2005年底微軟公司正式發布了C# 2.0,與C# 1.x相比,新版本增加了很多新特性,其中最重要的是對泛型的支持。通過泛型,我們可以定義類型安全的數據結構,而無需使用實際的數據類型。這能顯著提高性能並得到更高質量的代碼。泛型並不是什麼新鮮的東西,他在功能上類似於C++的模板,模板多年前就已存在C++上了,並且在C++上有大量成熟應用。
本文討論泛型使用的一般問題,比如為什麼要使用泛型、泛型的編寫方法、泛型中數據類型的約束、泛型中靜態成員使用要注意的問題、泛型中方法重載的問、泛型方法等,通過這些使我們可以大致了解泛型並掌握泛型的一般應用,編寫出更簡單、通用、高效的應用系統。
什麼是泛型
我們在編寫程序時,經常遇到兩個模塊的功能非常相似,只是一個是處理int數據,另一個是處理string數據,或者其他自定義的數據類型,但我們沒有辦法,只能分別寫多個方法處理每個數據類型,因為方法的參數類型不同。有沒有一種辦法,在方法中傳入通用的數據類型,這樣不就可以合並代碼了嗎?泛型的出現就是專門解決這個問題的。讀完本篇文章,你會對泛型有更深的了解。
為什麼要使用泛型
泛型是 2.0 版 C# 語言和公共語言運行庫 (CLR) 中的一個新功能。泛型將類型參數的概念引入 .Net Framework,類型參數使得設計如下類和方法成為可能:這些類和方法將一個或多個類型的指定推遲到客戶端代碼聲明並實例化該類或方法的時候。例如,通過使用泛型類型參數 T,您可以編寫其他客戶端代碼能夠使用的單個類,而不致引入運行時強制轉換或裝箱操作的成本或風險
為了了解這個問題,我們先看下面的代碼,代碼省略了一些內容,但功能是實現一個棧,這個棧只能處理int數據類型:
public class Stack
{
private int[] items;
private int count;
public Stack(int size)
{
items = new int[size];
count = 0;
}
public void Push(int x)
{
//為了代碼清晰及只簡單熟悉泛型因此不考慮堆棧時超出數組大小的情況
items[count++]=x;
}
public int Pop()
{
//為了代碼清晰及只簡單熟悉泛型因此不考慮出棧時超出數組已為空的情況
return items[--count];
}
}
class Test
{
static void Main()
{
Stack s = new Stack(10);
s.Push(111);
s.Push(222);
Console.WriteLine(s.Pop()+s.Pop())
}
}
上面代碼運行的很好,但是,當我們需要一個棧來保存string類型時,該怎麼辦呢?很多人都會想到把上面的代碼復制一份,把int改成string不就行了。當然,這樣做本身是沒有任何問題的,但一個優秀的程序是不會這樣做的,因為他想到若以後再需要long、Node類型的棧該怎樣做呢?還要再復制嗎?優秀的程序員會想到用一個通用的數據類型object來實現這個棧:
public class Stack
{
private object[] items;
private int count;
pub