You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承类还是实现接口?带名称的列表类设计方案抉择

带名称的值列表实现方案分析

已有接口定义:

interface INamedItem
{
  string Name { get }
}

需求为创建一个带名称的值列表,现有两种实现方案:

两种实现方式

方式一:继承List<ValueType>

class NamedValueList : List<ValueType>, INamedItem
{
  public string INamedItem.Name { get; set }
  ...
}

方式二:实现IList<ValueType>并委托内部列表

class NamedValueList : IList<ValueType>, INamedItem
{
  public string INamedItem.Name { get; set }
  private List<ValueType> _list = new List<ValueType>();
  public void Add(ValueType value)
  {
    _list.Add(value);
  }
 ...
}

方案选择的核心理由

这两种方案的选择绝非仅个人偏好,核心差异在于设计原则和后续扩展性:

不推荐方式一的原因

  • 违反里氏替换原则:List<ValueType>是为使用而非继承设计的——它没有提供可重写的virtual方法,若后续你需要修改Add等方法逻辑,只能用new关键字隐藏基类方法,这会导致多态场景下出现意外行为。
  • 暴露不必要的方法:继承List会让NamedValueList暴露所有List的公共方法(比如Clear、RemoveAll),可能不符合你对“带名称的值列表”的语义约束——比如你可能希望列表是只读的,或只能通过特定规则添加元素,但继承会让这些方法全部对外可见。

方式二的优势(委托内部列表)

  • 遵循组合优于继承原则:通过组合内部的List<ValueType>,你可以完全控制对外暴露的方法和行为。比如只实现IList中你需要的部分,或在委托前后添加自定义逻辑(比如添加元素时校验值、记录日志)。
  • 避免继承陷阱:不会因为基类List的内部实现变化而影响你的类,也不会出现里氏替换相关的问题。
  • 语义更清晰:你的类是“带名称的列表”,而非“一个额外加了名称的List”,组合方式更贴合这个语义。

关于“自行实现IList而非委托”

除非你有特殊需求(比如完全自定义存储结构、优化特定场景性能),否则完全没必要自行实现IList。委托给内部的List是最高效且安全的方式——既利用了List经过优化的成熟实现,又能保留自身类的设计灵活性。

内容的提问来源于stack exchange,提问作者Piglet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 07:35:01