与 C# 泛型、T、抽象有点混淆?

A little bit confusion with C# Generics, T, Abstraction ?

我是 Unity 的 C# 游戏制作者。我有收藏管理系统。

CollectableManager

public List<CollectableParent<Collectable>> collactableParentsList;

收藏父母

public class CollectableParent<T> : CollectableRelatedMonoBehaviour where T : Collectable

SpawnPointDefinedCollectableParent

public class SpawnPointParentDefinedCollectableParent<T> : CollectableParent<T> where T : Collectable

收藏品

public abstract class Collectable : CollectableRelatedMonoBehaviour, IHasPlayableSound

Collectable_Money

public class Collectable_Money : Collectable

CollectableParent_Money

public class CollectableParent_Money : SpawnPointParentDefinedCollectableParent<Collectable_Money>

问题

CollectableManager 中的

"collactableParentsList" 不接受 SpawnPointParentDefinedCollectableParent<Collectable_Money> 作为 T 定义为 "Collectable_Money" 的项,它是从 "Collectable" 派生的。如果我这样做 SpawnPointParentDefinedCollectableParent<Collectable>,它会被接受为列表中的项目。

这里的问题是,尽管 Collectable_MoneyCollectable 的子 class,但 而不是 使 SpawnPointParentDefinedCollectableParent<Collectable_Money> CollectableParent<Collectable>.

的子class

使用通用接口或许可以解决这个问题。如果我们将 CollectableParent<T> 更改为接口,并通过 out 修饰符将其定义为 T 中的 covariant。 (你还没有提供CollectableRelatedMonoBehaviour的定义,但也需要转换成接口):

public interface ICollectableParent<out T> : ICollectableRelatedMonoBehaviour where T : Collectable

如果您将列表定义为:

public static List<ICollectableParent<Collectable>> collectableParentsList;

然后就可以成功添加类型为SpawnPointParentDefinedCollectableParent<Collectable_Money>的项目了。

这里的关键部分是 ICollectableParent<T> 接口在 T 中是协变的。这使得传递实现 ICollectableParent<Collectable_Money> 的实例成为可能,其中需要 ICollectableParent<Collectable>

T 中将接口定义为协变确实引入了一些限制,具体而言(并且正如用于指示协变的 out 修饰符所暗示的那样),类型 T 只能是用作接口方法的 return 值。例如:

public interface ICollectableParent<out T> : ICollectableRelatedMonoBehaviour where T : Collectable
{
    // This is allowed - T is used as a return type
    T GetChild();
    // This is *not* allowed - T is used as a parameter
    void SetChild(T child);
}

您可以在此处阅读有关协方差及其逆(逆变)的更多信息:Difference between Covariance & Contra-variance