实现一个非常特殊的通用签名

时间:2013-09-13 14:15:15

标签: c# generics inheritance signature

我目前正在构建基于Unity的装饰模型的游戏引擎。我有三个类(SceneStateManager(一次只控制一个场景)>场景> SceneLayer> GameObject>组件)构成场景层次结构,除了名称和一些更小,非常具体的基本相同特征。 (在这种情况下,覆盖方法将执行此操作)

所有类都可以从父层次结构级别类类型初始化,并控制多个子级。由于类共享了许多常用功能,我想让它们从基类派生,该基类将共享功能分组以简化代码。

“超级基类”(ListJob<T>)是一个控制子项的类,到目前为止,所有前面提到的类型都是从它中派生出来的,以简化至少那部分。因此,处理本身的子代不需要包含在代码中,因为它已经很好地工作了。

我现在需要为基类获得一个适当的通用签名,所有场景层次结构类都将在以后派生。我当前的解决方案无法使用此错误进行编译:http://msdn.microsoft.com/en-us/library/bb384252(v=vs.100).aspx


我的通用签名和SceneSystemJob类的当前版本:

public abstract class SceneSystemJob<TItem, TParent> : ListJob<TItem>, IInitializable<TParent>  
    where TItem : IInitializable<SceneSystemJob<TItem, TParent>>
{  
    private TParent _Parent = default(TParent);

    public TParent Parent
    {
        get
        {
            return _Parent;
        }
        protected set
        {
            _Parent = value;
        }
    }

    // Implementation

    public void Initialize(TParent parent)
    {
        this.Parent = parent;
    }
}

SceneStateManager:

public class SceneStateManager // Controls only one Child and does not derive from super base class

场景:

public class Scene : SceneSystemJob<SceneLayer, SceneStateManager>

SceneLayer:

public class SceneLayer : SceneSystemJob<GameObject, Scene>

GameObject:

public class GameObject: SceneSystemJob<Component, SceneLayer>

组件:

public abstract class Component : Manager, IInitializable<GameObject>

Interface IInitializable:

public interface IInitializable<TParent>
{  
    void Initialize(TParent parent);  
}

如果您还需要更多代码,请告诉我。

1 个答案:

答案 0 :(得分:5)

除了重新使用更简单的系统之外,我不知道如何解决您的问题。这似乎过于设计了。

要解释您的代码错误的原因,请查看它的大大简化版本:

public interface IInitializable<TParent> { }
public class SceneSystemJob<TItem>  
    where TItem : IInitializable<SceneSystemJob<TItem>>
{ }
public class GameObject : SceneSystemJob<Component> { } // Error here
public class Component : IInitializable<GameObject> { }

错误是Component无法用作TItem。为什么不?这似乎有点合理:

  • TItem要求它实施IInitializable<SceneSystemJob<TItem>>
  • Component实施IInitializable<GameObject>
  • GameObject是一种特殊的SceneSystemJob<Component>>
  • 因此Component符合实施IInitializable<SceneSystemJob<Component>>
  • 的标准

遗憾的是,除非IInitializable<T>在T 中协变,否则结论不会出现。由于您的实际实现有一个方法,其中 in 一个T,它在T中不能协变。

以这种方式思考。 IInitializable<T>就像一个容器,可以放入T。约束说“你需要给我一个TItem,这样我就可以将任何 SceneSystemJob<TItem>放入容器中。”您正在为它提供一个容器,您可以 GameObject放入其中。因此不符合约束条件。

这就像约束所说:“我需要一个可以容纳任何动物的笼子”而且你把它交给了一个水族箱。那么,这是一个可以包含任何鱼的笼子,但约束并没有说“我需要一个笼子来为一些动物,你的选择”,它说它需要一个任何动物的笼子。

我不知道你是如何解决这个混乱的问题,除了重新开始而不是过于通用之外,你已经把自己搞得一团糟。