为什么不继承List

2024-03-08

在计划我的计划时,我经常从这样的一系列思考开始:

足球队只是足球运动员的名单。因此,我应该用:

var football_team = new List<FootballPlayer>();

此列表的顺序代表球员在名单中列出的顺序。

但后来我意识到,除了球员名单之外,球队还有其他必须记录的属性。例如,本赛季的总得分、当前预算、队服颜色、string代表团队的名称等。

那么我想:

好吧,一支足球队就像一份球员名单,但除此之外,它还有一个名字(一个string)和总分(int)。 .NET 没有提供用于存储足球队的类,因此我将创建自己的类。最相似和相关的现有结构是List<FootballPlayer>,所以我将从它继承:

class FootballTeam : List<FootballPlayer> 
{ 
    public string TeamName; 
    public int RunningTotal 
}

但事实证明指南说你不应该继承List<T> https://stackoverflow.com/a/5376343/1042555。我对这个指南在两个方面感到非常困惑。

Why not?

显然List以某种方式针对性能进行了优化 https://stackoverflow.com/a/5376358/1042555。为何如此?如果我扩展会导致什么性能问题List?究竟会破坏什么?

我看到的另一个原因是List由微软提供,我无法控制它,所以在公开“公共 API”之后,我无法稍后更改它 https://stackoverflow.com/questions/5376203/inherit-listt#comment6077237_5376343。但我很难理解这一点。什么是公共 API?我为什么要关心?如果我当前的项目没有也不可能有这个公共 API,我可以放心地忽略这个指南吗?如果我继承自List and原来我需要一个公共API,我会遇到什么困难?

为什么它很重要?列表就是列表。可能会改变什么?我可能想改变什么?

最后,如果微软不想让我继承List,他们为什么没有上课sealed?

我还应该使用什么?

显然,对于自定义集合,微软提供了Collection应该扩展的类而不是List。但是这个类很简陋,没有太多有用的东西,such as AddRange https://stackoverflow.com/questions/1474863/addrange-to-a-collection, 例如。jvitor83 的回答 https://stackoverflow.com/a/12039943/1042555提供了该特定方法的性能原理,但是速度如何缓慢?AddRange不比没有好AddRange?

继承自Collection比继承要多得多的工作List,我看不出有什么好处。当然,微软不会无缘无故地告诉我做额外的工作,所以我不禁觉得我在某种程度上误解了某些东西,并继承了Collection实际上不是解决我的问题的正确方法。

我见过诸如实施之类的建议IList。就是不行。这是几十行样板代码,对我没有任何帮助。

最后,一些人建议将List在某事上:

class FootballTeam 
{ 
    public List<FootballPlayer> Players; 
}

这样做有两个问题:

  1. 它使我的代码变得不必要地冗长。我现在必须打电话my_team.Players.Count而不是仅仅my_team.Count。值得庆幸的是,使用 C#,我可以定义索引器以使索引透明,并转发内部的所有方法List...但是代码太多了!所有这些工作我能得到什么?

  2. 简单来说这没有任何意义。足球队并没有“拥有”球员名单。它is球员名单。你不会说“John McFootballer 已加入 SomeTeam 的球员”。您说“约翰已加入 SomeTeam”。您不是向“字符串的字符”添加字母,而是向字符串添加字母。您不是将一本书添加到图书馆的图书中,而是将一本书添加到图书馆。

我意识到“幕后”发生的事情可以说是“将 X 添加到 Y 的内部列表中”,但这似乎是一种非常反直觉的思考世界的方式。

我的问题(总结)

表示数据结构的正确 C# 方式是什么?“逻辑上”(也就是说,“对于人类思维”)只是一个list of things有一些花哨的东西?

继承自List<T>总是无法接受?什么时候可以接受?为什么/为什么不呢?程序员在决定是否继承时必须考虑什么List<T> or not?


这里有一些很好的答案。我想补充以下几点。

表示数据结构的正确 C# 方式是什么?“逻辑上”(也就是说,“对于人类思维”)只是带有一些花哨的事物列表?

请任意 10 名熟悉足球存在的非计算机程序员来填空:

足球队是一种特殊的_____

Did anyone说“带有一些花哨的足球运动员名单”,还是他们都说“运动队”或“俱乐部”或“组织”?您认为足球队是一种特殊的球员名单存在于你的人类头脑中,并且仅存在于你的人类头脑中。

List<T> is a 机制。足球队是一支业务对象——也就是说,代表某个概念的对象业务领域的程序。不要混合这些!一支足球队是一种团队;它has a名册,名册是玩家列表。名册不是一个特定类型的球员名单。一个花名册is球员名单。所以创建一个名为Roster这是一个List<Player>。并做到ReadOnlyList<Player>当你这样做时,除非你相信每个了解足球队的人都可以从名单中删除球员。

继承自List<T>总是无法接受?

对谁来说不可接受?我?不。

什么时候可以接受?

当你建立一个机制时延长了List<T>机制.

程序员在决定是否继承时必须考虑什么List<T> or not?

我正在构建一个机制 or a 业务对象?

但这是很多代码!所有这些工作我能得到什么?

您输入问题所花费的时间比您为相关成员编写转发方法所花费的时间还要多List<T>五十次以上。显然,您并不害怕冗长,而且我们在这里讨论的是非常少量的代码;这是几分钟的工作。

UPDATE

我再仔细考虑了一下,还有另一个原因不将足球队建模为球员名单。事实上,将一支足球队建模为having还有球员名单。一支球队的问题在于/拥有一份球员名单,你所拥有的是snapshot团队的在某个时刻。我不知道这个类的商业案例是什么,但如果我有一个代表一支橄榄球队的类,我会想问它诸如“2003 年至 2013 年间有多少海鹰队球员因伤缺席比赛?”之类的问题。或“哪位之前为另一支球队效力过的丹佛球员跑码数同比增幅最大?”或者 ”今年猪猪队一路走好吗? http://theoatmeal.com/comics/working_home"

也就是说,在我看来,一支足球队可以很好地建模为历史事实的集合例如球员何时被招募、受伤、退役等。显然,当前球员名单是一个重要的事实,可能应该放在前面和中间,但是您可能想用这个对象做其他有趣的事情,需要更多历史视角。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么不继承List? 的相关文章

  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 如何将 #ifdef DEBUG 添加到 Xcode?

    我的项目中有一些代码永远不应该在发布版本中使用 但在测试时很有用 我想做这样的事情 ifdef DEBUG Run my debugging only code endif 在 Xcode 4 中哪里添加 DEBUG 设置 我尝试将其放入
  • 将内置类型转换为向量

    我的 TcpClient 类接受vector
  • 如何访问另一个窗体上的ListView控件

    当单击与 ListView 所在表单不同的表单中的按钮时 我试图填充 ListView 我在 Form1 中创建了一个方法以在 Form2 中使用 并将参数传递给 Form1 中的方法 然后填充 ListView 当我调试时 我得到了传递的
  • 生成(非常)大的非重复整数序列而不进行预洗牌

    背景 我编写了一个简单的媒体客户端 服务器 我想生成一个不明显的时间值 随从客户端到服务器的每个命令一起发送 时间戳中将包含相当多的数据 纳秒分辨率 即使它不是真正准确 因为现代操作系统中计时器采样的限制 等 我想做的 在 Linux 上
  • PyCharm 无法识别字典值类型

    我有一个简单的代码片段 其中我将字典值设置为空列表 new dict for i in range 1 13 new dict i 现在 如果在下一行的循环内我会输入new dict i 并添加一个点 我希望 PyCharm 向我显示可用于
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • openERP(odoo)中的继承

    我是 openERP 的新手 正在接受面试 请解释一下openERP中不同类型继承的想法 我认为总共有3种类型 请从面试的角度 用非常简单的方式解释一下 P S 我熟悉简单继承的概念 继承 继承机制用于创建可重用性的思想 可重用性意味着在任
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • Visual Studio 中的测试单独成功,但一组失败

    当我在 Visual Studio 中单独运行测试时 它们都顺利通过 然而 当我同时运行所有这些时 有些通过 有些失败 我尝试在每个测试方法之间暂停 1 秒 但没有成功 有任何想法吗 在此先感谢您的帮助 你们可能有一些共享数据 检查正在使用
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 有人可以提供一个使用 Amazon Web Services 的 itemsearch 的 C# 示例吗

    我正在尝试使用 Amazon Web Services 查询艺术家和标题信息并接收回专辑封面 使用 C 我找不到任何与此接近的示例 所有在线示例都已过时 并且不适用于 AWS 的较新版本 有一个开源项目CodePlex http www c
  • 如何从main方法调用业务对象类?

    我已将代码分为业务对象 访问层 如下所示 void Main Business object public class ExpenseBO public void MakeExpense ExpensePayload payload var
  • .NET中的LinkedList是循环链表吗?

    我需要一个循环链表 所以我想知道是否LinkedList是循环链表吗 每当您想要移动列表中的 下一个 块时 以循环方式使用它的快速解决方案 current current Next current List First 电流在哪里Linke
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 英特尔 Pin 与 C++14

    问题 我有一些关于在 C 14 或其他 C 版本中使用英特尔 Pin 的问题 使用较新版本从较旧的 C 编译代码很少会出现任何问题 但由于 Intel Pin 是操作指令级别的 如果我使用 C 11 或 C 14 编译它 是否会出现任何不良
  • 防止在工厂方法之外实例化对象

    假设我有一个带有工厂方法的类 class A public static A newA Some code logging return new A 是否可以使用 a 来阻止此类对象的实例化new 那么工厂方法是创建对象实例的唯一方法吗 当

随机推荐