我的所有对象都是由一个名为GameObject
的基本抽象类组成。所有这些对象都继承自一个或多个接口,例如IRenderable
,IAnimatable
,IMovable
等。
我还有一个存储为List<GameObject>
的对象列表。我正在尝试编写一个动态方法,它将返回从特定接口继承的所有对象,如下所示:
List<IRenderable> renderableObjects = ObjectManager.GetAll<IRenderable>();
首先,我尝试返回一个新的游戏对象列表,其中每个对象的类型与动态类型匹配,然后将List<GameObject>
强制转换为List<T>
。我收到的编译错误说我无法转换这些类型。
所以我的第二次尝试涉及单独投射每个对象,如下所示。
public List<T> GetAll<T>() {
List<T> list = new List<T>();
foreach( GameObject obj in this.gameObjects )
if( obj is T )
list.Add( (T)obj );
return list;
}
但是,这会引发相同类型的错误;无法将GameObject类型转换为T.我错过了什么?还有另一种方法可以实现我的目标吗?
答案 0 :(得分:5)
LINQ已经为您提供了一个非常方便的方法,OfType()
。
List<GameObject> list = ...;
var movableObjects = list.OfType<IMovable>();
OfType
将返回一个序列,其中包含输入序列中可以强制转换为您指定类型的所有项目。另外还有Cast<T>()
运算符,它只是试图强制转换所有内容,并且如果某个项目无法投射(这看起来不像你想要的那样)会抛出异常。
答案 1 :(得分:4)
Servy提供了更好的方法,但您也可以轻松修复代码。只需为T
泛型类型参数赋予约束:
public List<T> GetAll<T>() where T : GameObject {
另一个(更糟糕的)替代方案是添加额外的演员:
list.Add((T)(object)obj);
转换为泛型类型参数有点乱。有关详细信息,请参阅Eric Lippert's blog post。
(我肯定会使用Servy的方法 - 重新发明轮子没有意义 - 我只想解释如何在类似的情况下修复你的代码。)