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

Mor*_*unz 2 c# generics inheritance signature

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

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

"超级基类" (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;
    }
}
Run Code Online (Sandbox Code Playgroud)

SceneStateManager:

public class SceneStateManager // Controls only one Child and does not derive from super base class
Run Code Online (Sandbox Code Playgroud)

现场:

public class Scene : SceneSystemJob<SceneLayer, SceneStateManager>
Run Code Online (Sandbox Code Playgroud)

SceneLayer:

public class SceneLayer : SceneSystemJob<GameObject, Scene>
Run Code Online (Sandbox Code Playgroud)

游戏对象:

public class GameObject: SceneSystemJob<Component, SceneLayer>
Run Code Online (Sandbox Code Playgroud)

零件:

public abstract class Component : Manager, IInitializable<GameObject>
Run Code Online (Sandbox Code Playgroud)

接口IInitializable:

public interface IInitializable<TParent>
{  
    void Initialize(TParent parent);  
}
Run Code Online (Sandbox Code Playgroud)

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

Eri*_*ert 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> { }
Run Code Online (Sandbox Code Playgroud)

错误是Component不能用作的TItem.为什么不?这应该有效:

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

遗憾的是,除非在T中IInitializable<T>具有协变性,否则结论不会遵循前提.由于你的实际实现有一个接受T 的方法,它 T中不能协变.

这样想吧.An IInitializable<T>就像一个可以装入的容器T.约束说"你需要给我一个TItem这样的容器,我可以放入任何 容器SceneSystemJob<TItem>." 你给它一个你只能投入的容器GameObject.因此,不满足约束.

这就像约束说"我需要一个可以容纳任何动物的笼子"而你正在把它交给一个水族箱.嗯,这是可以包含一个笼子里什么鱼,但约束不说"我需要一个笼子里的一些动物,你的选择",它说,它需要一个笼子里的任何动物.

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