我有一个List<GKComponentSystem<GKComponent>>
和一个通用的Add<T>()
方法,其中T
是GKComponent
的约束。
为什么不能将GKComponentSystem<T>
的实例添加到列表中?请参见下面的代码片段:
List<GKComponentSystem<GKComponent>> _systems = new List<GKComponentSystem<GKComponent>>();
public void AddSystem<T>(int position = -1) where T : GKComponent
{
var system = new GKComponentSystem<T>();
_systems.Add(system);
}
错误:
参数1无法转换GameplayKit.GKComponentSystem 表达式
键入GameplayKit.GKComponentSystem
在
_systems.Add(system)
行中。我以为我知道C#,但这是我很高兴拥有StackOverflow的情况之一-在这里我不了解什么呢?
system
是GKComponentSystem<T>
,并且T
必须是GKComponent
,所以system
是GKComponentSystem<GKComponent>
,我应该可以将其添加到列表中。这是
GKComponentSystem
:public class GKComponentSystem<T> : NSObject where T : GKComponent
它的
T
也是GKComponent
...这是关于协变性的吗(我肯定是必须学习更多的话题)?
最佳答案
这是一个更简单的示例:
class Parent
{
}
class Child : Parent
{
}
class GenericClass<T>
{
}
Parent p;
p = new Child(); // A child inherits from Parent, so this is allowed.
GenericClass<Parent> gp;
gp = new GenericClass<Child>(); // Not allowed! GenericClass<Child> does not inherit from GenericClass<Parent>
在您的示例中,
T
继承自GKComponent
的事实并未转化为GKComponentSystem<T>
可以转换为GKComponentSystem<GKComponent>
的规则。因此,现在将其应用于列表。
List<Parent> l = new List<Parent>();
l.Add(new Child()); // A child can be converted to a Parent, this is OK
List<GenericClass<Parent>> gl = new List<GenericClass<Parent>>();
gl.Add(new GenericClass<Child>()); // A GenericClass<Child> does not convert to GenericClass<Parent>, so this is not allowed.
如果您确实希望这样做,可以定义一个通用接口。这些允许您使用
out
指定通用参数,如下所示: interface IGenericClass<out T>
{
}
class GenericClass<T> : IGenericClass<T>
{
}
IGenericClass<Child> gcChild = new GenericClass<Child>();
IGenericClass<Parent> gcParent = gcChild; // This is allowed!
var l = new List<IGenericClass<Parent>>();
l.Add(new GenericClass<Child>()); // Also allowed
因此,将其应用于您的示例:
interface IGKComponentSystem<out T>
{
}
class GKComponentSystem<T> : IGKComponentSystem
{
}
List<IGKComponentSystem<GKComponent>> _systems = new List<IGKComponentSystem<GKComponent>();
// Should work from there...
public void AddSystem<T>(int position = -1) where T : GKComponent
{
var system = new GKComponentSystem<T>();
_systems.Add(system);
}