最近在學習.NET 2.0了(說來慚愧呀,萬多年前就出VS2005了,現在才想起學.NET 2.0),粗略看了下,2.0版本較1.1版本多了不少新的特性,比如MaterPage,Theme,無重新整理Call Server等,頁面生命週期也多了不少方法,可以更精確的控制頁面的呈現過程,令人激動呀。不過今天要說的不是.NET FrameWork 2.0,而是新版C#中的新特性:泛型
還是先看看下面一段代碼吧:
using System;
using System.Collections.Generic;
using System.Text;
namespace TestConsole2005
{
public interface ITest
{
void dosth();
}
public class TestClass:ITest
{
public TestClass()
{ }
ITest Members#region ITest Members
void ITest.dosth()
{
Console.WriteLine("testing1");
}
#endregion
}
public class TestClass2 : ITest
{
public TestClass2()
{ }
ITest Members#region ITest Members
void ITest.dosth()
{
Console.WriteLine("testing2");
}
#endregion
}
public class Test<T,T2> where T:ITest,new() where T2:ITest,new()
{
private T mt;
private T2 mt2;
public Test()
{
mt = new T();
mt2 = new T2();
}
public void foo()
{
mt.dosth();
mt2.dosth();
}
}
class Program
{
static void Main(string[] args)
{
Test<TestClass, TestClass2> v = new Test<TestClass1, TestClass2>();
v.foo();
Console.ReadLine();
}
}
}
泛型為我們解決了什麼問題呢?
在沒有泛型以前,我們在定義變數時都是將它的類型寫入程式碼,比如:
TestClass mt = new TestClass();
這樣在用戶端就沒有辦法改變mt的類型了,除非使用反射,但反射是在運行時指定類型資訊,泛型則不同,泛型是在用戶端編碼時指定類型資訊,比如上面的:
Test<TestClass, TestClass2> v = new Test<TestClass, TestClass2>();
這一句就是在執行個體化Test類時為T和T2指定詳細的類型資訊。
把這個與下面的運行結果做個比較(只是把類型互換了)就知道泛型的工作方式了:
Test<TestClass2, TestClass> v = new Test<TestClass2, TestClass>();
為什麼要使用泛型,其實反射也一樣可以實現這樣的功能。原因在於使用泛型可以保證類型的安全,而反射是到運行時才綁定類型資訊,這樣就很有可能出現類型不符的情況,而編譯器是無法發現的。
最後說明下:
Public class Test<T,T2> where T:ITest,new() where T2:ITest,new()
T和T2聲明了Test類中的兩個泛型型別,他們可以在用戶端執行個體化該類時被顯式指定,where是C#2005才有的用於約束泛型型別的關鍵字,上面的運算式是指泛型T和T2必須指定為實現了ITest介面的類,並且該類可以被執行個體化。
泛型還可以代替傳統的簡單原廠模式,總之,泛型的出現是為了支援用戶端指定類型資訊,而反射是運行時指定類型資訊。