为什么不从列表继承<T>?

在规划我的计划时,我通常会从这样的一系列想法开始:

足球队就是足球运动员的名单。因此,我应该用以下方式来表示:

var football\u team=新列表<足球运动员>();

这份名单的顺序代表了球员在名册上的排列顺序

但我后来意识到,除了球员名单之外,球队还有其他必须记录的属性。例如,本赛季的总成绩、当前预算、统一颜色、代表球队名称的字符串等

所以我想:

好的,足球队就像一张球员名单,但除此之外,它还有一个名字(一个字符串)和一个总得分(一个int)。NET不提供用于存储足球队的类,因此我将创建自己的类。最相似和最相关的现有结构是List<足球运动员&gt,因此我将从中继承:

职业足球队:名单<足球运动员>
{ 
公共字符串组名;
公共整数运行总计
}

但事实证明,一条指导方针说,您不应该从List<T&gt。我完全被这条指导方针搞糊涂了

为什么不呢

显然,List以某种方式优化了性能。为什么呢如果扩展列表,会导致哪些性能问题?到底什么东西会断裂

我看到的另一个原因是List是由微软提供的,我对它没有控制权,所以在公开了“公共API”之后,我以后无法更改它。但我很难理解这一点。什么是公共API?我为什么要关心它?如果我当前的项目没有也不可能有这个公共API,我可以安全地忽略这个指南吗?如果我确实继承了列表并且发现我需要一个公共API,那么我会遇到什么困难

为什么这很重要?清单就是清单。有什么可能改变?我可能想要改变什么

最后,如果微软不想让我继承列表,为什么他们不让类密封

我还能用什么

显然,对于自定义集合,Microsoft提供了一个集合类,该类应该扩展,而不是列表。但是这个类非常简单,没有很多有用的东西,例如AddRange。jvitor83的回答提供了该特定方法的性能原理,但是缓慢的AddRange如何不比没有AddRange好呢

集合继承要比从列表继承多得多,我看不出有什么好处。当然,微软不会无缘无故地告诉我做额外的工作,所以我忍不住觉得自己在某种程度上误解了什么,而继承集合实际上并不是解决我问题的正确方法

我看到了一些建议,比如实现IList。只是没有。这是几十行的样板代码,我什么也得不到

最后,一些人建议将列表包装成以下内容:

职业足球队
{ 
公开名单<足球运动员>球员;
}

这有两个问题:

  1. 它使我的代码变得不必要的冗长。我现在必须调用我的团队.Players.Count而不是我的团队.Count。谢天谢地,有了C#我可以定义索引器使索引透明,并转发内部列表的所有方法。。。但这是很多代码!那些工作我能得到什么

  2. 这显然没有任何意义。足球队没有球员名单。这是球员名单。你不会说“约翰·麦克斯波尔加入了某支球队的球员”。你说“约翰加入了某个团队”。您不会在“字符串的字符”中添加字母,而是在字符串中添加字母。你不是在图书馆的书中添加一本书,而是在图书馆中添加一本书

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

我的问题(摘要)

正确的C#表示数据结构的方式是什么,“逻辑上”(也就是说,“对人的头脑来说”)只是一个列表,包含事物,只需几声钟声和口哨

继承自列表<T&gt总是不可接受?什么时候可以接受?为什么?程序员在决定是否继承列表>时,必须考虑什么?T&gt还是不

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

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

请任何十位熟悉足球存在的非计算机程序员填写以下空白:

足球队是一种特殊的运动_____

有没有人说“带着一些铃铛和口哨的足球运动员名单”,或者他们都说“运动队”或“俱乐部”或“组织”?你认为一支足球队是一种特殊的球员名单,这种想法存在于你的人类思维中,也仅存在于你的人类思维中

列表<T&gt是一种机制。足球队是一个业务对象——也就是说,一个代表项目业务领域中某些概念的对象。别把它们混在一起!足球队是一种球队;它有一个花名册,花名册是一个球员名单。花名册不是一个特定类型的球员名单。花名册是球员名单。因此,创建一个名为花名册的属性,它是一个列表<播放器&gt。并使其ReadOnlyList<播放器&gt当你这样做的时候,除非你相信每个了解足球队的人都可以从名单中删除球员

继承自列表<T&gt总是不可接受

谁不能接受?我没有

什么时候可以接受

当您正在构建一个扩展列表的机制时<T&gt机构

当程序员决定是否从列表中继承时,程序员必须考虑什么?T&gt还是不

我是在构建一个机制还是一个业务对象

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

您花了更多的时间输入您的问题,这将花费您为List<的相关成员编写转发方法;T&gt50次以上。很明显,您并不害怕冗长,我们在这里讨论的是非常少量的代码;这是几分钟的工作

更新

我对此进行了更多的思考,还有另一个理由不将足球队作为球员名单来建模。事实上,将一支足球队建模为同时拥有一份球员名单可能不是一个好主意。有球员名单的球队的问题在于,你得到的是球队在某一时刻的快照。我不知道你在这门课上的商业案例是什么,但如果我有一门代表足球队的课,我想问一些问题,比如“在2003年到2013年间,有多少海鹰队的球员因为伤病错过了比赛?”或者“之前为另一支球队效力的丹佛队球员的跑位同比增长最大?”“今年猪圈走到哪里去了?”

也就是说,在我看来,足球队似乎是一个历史事实的集合,例如球员被招募、受伤、退役等。显然,当前的球员名册是一个重要的事实,可能是最重要的事实,但可能还有其他有趣的事情需要你来处理更具历史意义的观点

发表评论