我有一个List<GKComponentSystem<GKComponent>>和一个通用的Add<T>()方法,其中TGKComponent的约束。

为什么不能将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的情况之一-在这里我不了解什么呢?

systemGKComponentSystem<T>,并且T必须是GKComponent,所以systemGKComponentSystem<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);
 }

07-28 01:04