C# 从另一个泛型类添加泛型方法约束

C# 从另一个泛型类添加泛型方法约束,c#,.net,generics,C#,.net,Generics,我不确定标题是否反映了我的意思,但是.. 假设我有两个类,实体和组件: public abstract class Entity { private List<Component> _components = new List<Component>(); public void AddComponent<T>() where T : Component { T component = (T)Activa

我不确定标题是否反映了我的意思,但是..
假设我有两个类,
实体
组件

public abstract class Entity
{
    private List<Component> _components = new List<Component>();

    public void AddComponent<T>()
        where T : Component
    {
        T component = (T)Activator.CreateInstance(typeof(T));
        component.Owner = this;

        _components.Add(component);
    }
}

public abstract class Component
{
    public Entity Owner { get; protected set; }

    public abstract void Update();
}
public abstract class Entity
{
    private List<Component> _components = new List<Component>();

    public void AddComponent<T>()
        where T : Component
    {
        T component = (T)Activator.CreateInstance(typeof(T));
        component.Owner = this;

        _components.Add(component);
    }
}

public abstract class Component
{
    public Entity Owner { get; protected set; }

    public abstract void Update();
}

public abstract class Component<T> : Component
{
    // I hide the base.Owner with new keyword
    // feel free to suggest me in case there is better approach to do this
    new public T Owner 
    { 
        get { return (T)base.Owner; } 
        protected set { base.Owner = value; }
    }
}
现在,假设我有
Foo
Bar
Processor
类:

public class Foo : Entity
{
    public int FooValue { get; set; }
}

public class Bar : Entity
{
    public int BarValue { get; set; }
}

public class Processor : Component<Foo>
{
    public override void Update()
    {
        Owner.FooValue = 10;
    }
}
我也试着这样做:

public void AddComponent<T, X>()
    where T : Component<X>
    where X : Entity
{
    T component = (T)Activator.CreateInstance(typeof(T));
    component.Owner = this;

    _components.Add(component);
}
public void AddComponent()
其中T:组件
其中X:实体
{
T component=(T)Activator.CreateInstance(typeof(T));
component.Owner=this;
_组件。添加(组件);
}
但是,它要求我明确指定X约束:

foo.AddComponent<Processor, Foo>();
bar.AddComponent<Processor, Bar>(); // Error, but the syntax is weird!
foo.AddComponent();
bar.AddComponent();//错误,但语法很奇怪!

有什么想法吗?

您的帖子不清楚您对基本
实体
组件
类有哪些限制(如果有)。因此,我不知道以下这些在您的场景中是否可行。也就是说,我相信如果不是这样,您将无法执行您想要的操作,因为否则编译器将不知道泛型类型参数

在没有任何其他约束的情况下,解决方案是将
实体
类设置为泛型,并提供子类类型本身作为类型参数:

class Entity { }

class Entity<T> : Entity where T : Entity<T>
{
    public void AddComponent<U>(U value) where U : Component<T> { }
}

class Component<T> where T : Entity { }

class Foo : Entity<Foo> { }

class Bar : Entity<Bar> { }

class P : Component<Foo> { }

注意:我强烈建议不要隐藏类成员。正如前面所说,这并不会真正影响你的问题(也就是说,你可以完全忽略这个细节),但是拥有两个同名的不同属性只是在问bug。如果必须使用隐藏,那么至少应该让新属性使用隐藏属性。例如:

class Component
{
    public Entity Owner { get; protected set; }
}

class Component<T> : Component where T : Entity
{
    new public T Owner
    {
        get { return (T)base.Owner; }
        set { base.Owner = value; }
    }
}
类组件
{
公共实体所有者{get;protected set;}
}
类组件:组件,其中T:实体
{
新公营房屋业主
{
获取{return(T)base.Owner;}
set{base.Owner=value;}
}
}

对于非泛型
组件.Owner
属性的赋值,您不会得到编译时检查,但如果某些代码试图将
Owner
属性取消引用为泛型版本,如果基类型出于某种原因分配了错误的类型,至少会得到运行时错误。

谢谢您的回答,这似乎是我想要的东西!但是,在某些情况下,<代码> Fo< <代码>或<代码> Bar <代码>是用另一个类继承的,考虑这2个类:<代码>:Fo< < /代码>和<代码>:Bar < /代码>(当然还有<代码> Fo:实体< /代码>和<代码> BAR:实体< /代码>),在这种情况下,是否有可能创建一个只能由类
B
附加的
组件
?具体取决于您的意思。可以将基类设置为泛型(
class Foo:Entity,其中T:Entity
),然后可以在派生类中指定类型参数:
class A:Foo
class B:Foo
。您甚至可以制作非通用版本的
Foo
类Foo:Foo
。上述内容应解决您最初提出的问题。如果你想探索更多的选择,我建议你尝试上述方法;如果你遇到麻烦,你可以随时发布一个新的问题来引用这个问题。
Foo foo = new Foo();
Bar bar = new Bar();
P p = new P();

foo.AddComponent(p);
bar.AddComponent(p); // CS0311
class Component
{
    public Entity Owner { get; protected set; }
}

class Component<T> : Component where T : Entity
{
    new public T Owner
    {
        get { return (T)base.Owner; }
        set { base.Owner = value; }
    }
}