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; }
}
}