如何将对象转换为动态类型?

时间:2012-11-08 21:10:12

标签: c# .net .net-4.0

我的所有对象都是由一个名为GameObject的基本抽象类组成。所有这些对象都继承自一个或多个接口,例如IRenderableIAnimatableIMovable等。

我还有一个存储为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.我错过了什么?还有另一种方法可以实现我的目标吗?

2 个答案:

答案 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的方法 - 重新发明轮子没有意义 - 我只想解释如何在类似的情况下修复你的代码。)