我有一个抽象类:
abstract class A {
// some stuff
float val = 0;
abstract float Foo();
}
class B1 : A {
override float Foo() {
Console.WriteLine("B1: " + val);
}
}
class B2 : A {
override float Foo() {
Console.WriteLine("B2: " + val);
}
}
而且我有一个List<A> a
,我想得到给定类型T的第一项:
public T GetTypeFromList<T>() {
foreach (var item in a) {
T tmp = item as T; // doesn't compile
if (tmp != null)
return tmp;
}
throw new Exception("Type isn't in list.");
}
有办法吗?编辑:它显示:类型参数“ T”不能与“ as”运算符一起使用因为它没有类类型约束也没有“类”约束
为了使代码正常工作,您必须在方法中添加where
约束:
static T GetTypeFromList<T>(List<A> a) where T: class
,然后它将起作用。
因为在使用as
关键字时,它将对象转换为给定的引用或可为空的值类型。如果转换失败,则as
运算符的结果将为null
。并且null
仅对可为空的类型有效。为了使编译器满意,您必须在方法签名中添加class
约束。
But,为此目的,在System.Linq
命名空间中已经有内置方法出口。它称为OfType<>
。它根据指定的类型过滤OfType<>
的元素。
IEnumerable
并且为了获得第一个项目,您可以使用var b2s = list.OfType<B2>();
或First()
,如果集合中不存在此元素,则它们将返回FirstOrDefault()
:
null
顺便说一句,如果您看一下var b2 = list.OfType<B2>().FirstOrDefault();
的实现,您会看到它返回OfType<>
,并且在该方法内部,它仅遍历集合并使用OfTypeIterator
运算符查找带有所需类型:
OfTypeIterator
一种方法是使用LINQ is
方法。它将检查每个元素的类型并返回匹配的第一个元素,如果找不到目标类型,则抛出异常:
static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source) {
foreach (object obj in source) {
if (obj is TResult) yield return (TResult)obj;
}
}
顺便说一句:.First
只能使用运算符List<A> myList;
MyTargetType obj = (MyTargetType)myList.First(e => e is MyTargetType);
。
请勿使用as
检查类型。使用reference and nullable types代替:
as