我熟悉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