【问题标题】:List of children with Generics [duplicate]具有泛型的儿童名单[重复]
【发布时间】:2018-01-17 09:18:41
【问题描述】:

我需要在一个列表中保留几个基类的孩子。通常不是问题,但由于涉及泛型,这让我很头疼。我的基类如下所示:

public abstract class Equipment<T> where T:EquipmentData { }

现在的孩子可能看起来像:

public class Weapon : Equipment<WeaponData> { }

public class WeaponData : EquipmentData { }

类似的还有:

public class Shield : Equipment<ShieldData> { }
public class ShieldData : EquipmentData { }

现在我需要一个包含Equipment&lt;T&gt; 的子级的列表,但显然List&lt;T&gt; 要求我更具体,例如List&lt;Equipment&lt;EquipmentData&gt;&gt;。但是,当我尝试将Weaponobject 添加到该列表时,我收到无法将Weapon 转换为Equipment&lt;EquipmentData&gt; 的错误。当然,将列表更改为 List&lt;Equipment&lt;WeaponData&gt;&gt; 会起作用,但是出于同样(显而易见的)原因,我将无法将 Shieldobjects 添加到该列表中。

本质上我的问题是是否有某种方法可以使列表成为一个

List&lt;Equipment&lt;child ofEquipmentData>> 这样它就需要Weapon 对象以及Shieldobjects?

【问题讨论】:

  • 这是对泛型的错误使用。不要这样做。正如您所发现的,当您尝试组合多种多态性时,它会导致问题。请参阅我的系列ericlippert.com/2015/04/27/wizards-and-warriors-part-one,了解更多关于这种模式的具体想法,以及在 FRP 游戏中表示武器的类似模式。
  • 任何时候你有一个模式,其中有两个类层次结构必须保持同步并通过约束相互关联,你就会遇到这样的问题。参数化基类不会给你带来什么
  • 如果您坚持,请参阅第一个副本以获取选项。您必须为Equipment&lt;T&gt; 创建一个非泛型基类型,因此您的所有类都共享一个它们都兼容的类型。但恕我直言,这是一个糟糕的方式(对不起,马克)。请参阅第二个标记的副本以了解您为什么不想这样做的信息,当然还有 Eric 的很好的系列文章,该系列阐述了该主题。
  • @EricLippert 我明白你的意思。不过,它实际上不是一个同步的层次结构。通常所有Equipment 共享相同的EquipmentData 只是在少数情况下需要额外数据(例如射击的视觉效果(射击、轨迹、冲击)或武器子弹的速度或我需要EquipmentData 的孩子的船周围的盾牌(模型,材料))。出于工作流程的原因,我尝试将 EquipmentData 和来自武器的特殊数据保留在同一个对象中,以便通过 Unity Inspector 更轻松地进行平衡操作。

标签: c# generics


【解决方案1】:

我怀疑这样做的唯一方法是添加一个通用的非泛型基类,也许:

public abstract class Equipment { }
public abstract class Equipment<T> : Equipment where T : EquipmentData { }

使用List&lt;Equipment&gt;,其中Equipment 具有您在不知道类型的情况下需要访问的任何基本功能。如果您将任何非特定成员添加到基类,您可以使用成员隐藏 (new) 在 Equipment&lt;T&gt; 类型中使用更具体的类型重新声明它们。

如果您愿意,也可以使用IEquipment 接口做同样的事情。

【讨论】:

  • 由于问题是在列表中使用时所讨论的类型不能以协变方式变化,因此它们可能必须是接口。但我认为更好的设计是在两个并行的类层次结构之间完全不存在这种关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
  • 2020-03-30
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多