如何将抽象类转换为T类型?

问题描述 投票:3回答:3

我有一个抽象类:

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”运算符一起使用因为它没有类类型约束也没有“类”约束

c#
3个回答
2
投票

为了使代码正常工作,您必须在方法中添加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

1
投票

一种方法是使用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);


0
投票

请勿使用as检查类型。使用reference and nullable types代替:

as
© www.soinside.com 2019 - 2024. All rights reserved.