C#泛型和类型检查混淆

时间:2011-08-26 22:25:27

标签: c# generics types

首先,开始一些课程:

public abstract class Component
{
    GenericSystem mySystem;

    public Component() { mySystem = null;}

    public void SetSystem(GenericSystem aSystem) { mySystem = aSystem; }
}

public class PhysicsComponent : Component
{
    int pos;    

    public PhysicsComponent(int x) : base() { pos = x; }
}


public abstract class GenericSystem : List<Component>
{
    public Type ComponentType;
    public GenericSystem(Type componentType)
    { ComponentType = componentType; }
    public void RegisterComponent(c)
    {
        Add(c);
        c.SetSystem(this);
    }
}

public class PhysicsSystem : GenericSystem
{
    public PhysicsSystem() : base(typeof(PhysicsComponent)) { }
}

public static GenericEngine
{
    List<GenericSystem> systems = new List<GenericSystem>();

    //... Code here that adds some GenericSystems to the systems ...

    public static void RegisterComponent(Component c)
    {
        foreach(GenericSystem aSystem in systems)
        {
            Type t = aSystem.ComponentType;
            //PROBLEM IS HERE
            t c_as_t = c as t;
            //
            if ( c_as_t != null)
                aSystem.RegisterComponent(c);
        }


    }

}

我得到的错误是“无法找到类型或命名空间'。”

我希望每个GenericSystem都有一个它想要注册的Component类型。这样,注册新Component c的任何内容只需调用GenericEngine.RegisterComponent(c),所有对该类型组件感兴趣的系统都会注册它。

理想情况下,我希望代码更符合以下几行:

     //where T must be a child of Component
    public abstract class GenericSystem<T> : List<Component> { /... }
    public class PhysicsSystem : GenericSystem<PhysicsComponent>

我怀疑这不是一个非常复杂的问题,而且我错过了一些关于C#如何处理类型(或者更令人尴尬的是一般的泛型)的内容,所以如果这是一个简单的问题,请指出我的方向一些阅读材料。提前谢谢!

2 个答案:

答案 0 :(得分:9)

局部变量声明和“as”不起作用。 “t”是在运行时计算为对表示类型的对象的引用的表达式。本地decl和“as”期望一个程序片段在编译时命名一个类型

你试图把蛋糕放在一堆蛋糕食谱书上;虽然蛋糕和蛋糕食谱书密切相关,但它们并不是一回事。

如果要确定在运行时是否对象c是t对象描述的类型,那么可以在c上调用GetType并确定这两种类型是否(1)相等,如果您需要标识,或者(2)兼容,如果你只需要一个兼容另一个。


  

理想情况下,我希望代码更符合以下几行:

 //where T must be a child of Component
public abstract class GenericSystem<T> : List<Component>

好的,然后说:

public abstract class GenericSystem<T> : List<Component> where T : Component 

看看你的设计,其他事情似乎很可疑。通用系统实际上是一种组件列表,还是包含组件列表之类的东西?使用推导来表达“是一种”关系。使用包含来表达“容器”关系。汽车不是一种车轮清单;汽车 一个轮子列表。

答案 1 :(得分:1)

首先,你正在写

if ((c as T) != null)

更简单

if (c is T)

然后,正如Eric指出的那样,这些运算符需要类型,而不是包含类型元数据的变量。你需要反思,比如:

if (t.IsAssignableFrom(c.GetType()))