我熟悉Java和.NET泛型,我在我的Java項目中使用了很多像這樣的構造。我最喜歡的用途之一是應對非Java的泛型集合這是從Hibernate等外部的代碼返回(我認爲Hibernate的最新版本可能支持泛型,但我不能肯定這一點。我們正在使用相當因爲舊版本的它是有太多的代碼,就必須更新,如果我們永遠改變了它一個長期運行的項目)的功能是這樣的:。
public <X> List<X> TypedList(List<?> lst, Class<X> cls) {
return (List<X>) lst;
}
這一切都非常簡單,最重要的事情是我沒有創建一個虛擬對象傳遞給函數,我只是把它作爲:
List<MyObject> myLst = TypedList(lst, MyObject.class);
需要注意的另一個重要的事情是cls參數完全不用。這只是給人一種具體類型爲X.
你做同樣的事情在C#中有一點點不同的方式表示。你可能會認爲同樣的功能會是這個樣子:
public List<X> TypedList<X>(IList lst)
{
return (List<X>) lst;
}
但是,你就死定了錯誤的。
的問題是,Java使用一種稱爲類型擦除招,這基本上意味着,當代碼實際上是編譯,所有的通用參數從代碼中刪除。所以在Java虛擬機的世界裏,有沒有這樣的事,作爲一個List<X>
或任何其他仿製藥,它們都是簡單的List
和其他非泛型類型。這意味着泛型僅用於幫助您編碼,並且不會在運行時強制執行。
但是,在C#中沒有類型擦除和泛型是在運行時強制執行。這意味着,與上述功能時使用以下將產生一個運行時異常:
List<object> lstObj = TypedList<object>(new List<string>());
其原因是,List<string>
和List<object>
被認爲是兩個完全不同的類。如果沒有編譯器錯誤,你甚至不能執行List<object> lstObj = (List<object>) new List<string>();
。 這意味着函數不能返回傳遞給它的同一個對象。我們必須創建正確類型的新對象,並返回一個。最基本的形式如下:
public List<X> TypedList<X>(IList lst)
{
List<X> lstOut = new List<X>();
for (int i = 0; i < lst.Count; i++)
{
if (lst[i] is X) lstOut.Add((X) lst[i]);
}
return lstOut;
}
這是相當無聊和樣板代碼,但它的工作原理。對於更短更乾淨的東西,LINQ在這裏是爲了節省一天的時間。看看下面的:
public List<X> TypedList<X>(IList lst)
{
return lst.OfType<X>().ToList();
}
OfType<X>()
抓住LST中屬於X型(或後代)的所有項目,並跳過任何都沒有。 ToList()
然後建立一個新的List<X>
包含從OfType<X>()
傳遞給它的所有成員。這種方法的另一個優點是,我們實際上可以善堂參數從一種IList
到IEnumberable
,這是所有的集合類型實現的改變。
另一件需要指出的事情是,它不做類型轉換,只進行類型檢查。所以這意味着如果你想採取List<long>
並將其轉換爲List<int>
或List<string>
,那麼你需要做其他事情。隨着LINQ,這仍然會是很簡單的:
List<long> lstLng = new List<long>();
lstLng.Add(1);
List<int> lstInt = lstLng.Cast<int>().ToList();
List<string> lstStr = lstLng.Select(lng => lng.ToString()).ToList();
[注:如果你不熟悉的lng => lng.ToString()
部分,它被稱爲Lambda表達式]
Cast<int>()
,不像OfType<int>()
,實際上會嘗試將每個項目轉換爲一個int,跳過所有無法轉換的項目。 Select()
只是讓你從現有的集合中構建一個全新的集合,使用幾乎任何你想要的代碼。
我希望我的真實世界的例子有助於人們更好地理解.NET和Java在使用泛型類型函數時的差異。
http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx – asawyer 2011-04-19 20:34:57
我不是一個C#程序員,但我認爲這個習語很少見在C#中,因爲C#沒有類型擦除。通用類型信息在運行時保留,不會丟失。 – 2011-04-19 20:35:45
不要以爲有一個。 – clamchoda 2011-04-19 20:35:49