前言
.net 2.0中泛型的出現是一個令人激動的特徵。但是,什麼是泛型?你需要它們嗎?你會在自己的應用軟體中使用它們?在本文中,我們將回答這些問題並細緻地分析泛型的使用,能力及其局限性。
型別安全
.net中的許多語言如c#,c++和vb.net(選項strict為on)都是強型別語言。作為一個程式員,當你使用這些語言時,總會期望編譯器進行型別安全的檢查。例如,如果你把對一個book類型的引用轉換成一個vehicle型的引用,編譯器將告訴你這樣的cast是無效的。
然而,當談到.net 1.0和1.1中的集合時,它們是無助於型別安全的。請考慮一個arraylist的例子,它擁有一個對象集合--這允許你把任何類型的對象放於該arraylist中。讓我們看一下例1中的代碼。
例1.缺乏型別安全的arraylist
using system;
using system.collections;
namespace testapp
{
class test
{
[stathread]
static void main(string[] args)
{
arraylist list = new arraylist();
list.add(3);
list.add(4);
//list.add(5.0);
int total = 0;
foreach(int val in list)
{
total = total + val;
}
console.writeline("total is {0}", total);
}
}
}
本例中,我們建立了一個arraylist的執行個體,並把3和4添加給它。然後我迴圈遍曆該arraylist,從中取出整型值然後把它們相加。這個程式將產生結果"total is 7"。現在,如果我注釋掉下面這句:
list.add(5.0);
程式將產生如下的運行時刻異常:
unhandled exception: system.invalidcastexception: specified cast is not valid.
attestapp.test.main(string[]args)in :workareatestappclass1.cs:line 17
哪裡出錯了呢?記住arraylist擁有一個集合的對象。當你把3加到arraylist上時,你已把值3裝箱了。當你迴圈該列表時,你是把元素拆箱成int型。然而,當你添加值5.0時,你在裝箱一個double型值。在第17行,那個double值被拆箱成一個int型。這就是失敗的原因。
注意:上面的執行個體,如果是用vb.net書寫的話,是不會失敗的。原因在於,vb.net不使用裝箱機制,它啟用一個把該double轉換成整型的方法。但是,如果arraylist中的值是不能轉換成整型的,vb.net代碼還會失敗。
作為一個習慣於使用語言提供的型別安全的程式員,你希望這樣的問題在編譯期間浮出水面,而不是在運行時刻。這正是泛型產生的原因。
3. 什麼是泛型?
泛型允許你在編譯時間實作類別型安全。它們允許你建立一個資料結構而不限於一特定的資料類型。然而,當使用該資料結構時,編譯器保證它使用的類型與型別安全是相一致的。泛型提供了型別安全,但是沒有造成任何效能損失和代碼臃腫。在這方面,它們很類似於c++中的模板,不過它們在實現上是很不同的。