为什么不从List <T>继承?
在规划我的节目时,我经常从一系列的想法开始,比如:
足球队只是一个足球运动员的名单。 因此,我应该用:
var football_team = new List<FootballPlayer>();
此列表的排序表示球员列入名单的顺序。
但我后来认识到,除了仅仅是球员名单之外,球队还有其他属性,必须记录下来。 例如,本赛季得分总数,当前预算,统一颜色,代表球队名称的string
等。
那么我想:
好吧,足球队就像一个球员列表,但另外它有一个名字(一个string
)和一个总分数(一个int
)。 .NET不提供存储橄榄球队的类,所以我会自己创建类。 最相似和相关的现有结构是List<FootballPlayer>
,所以我将继承它:
class FootballTeam : List<FootballPlayer>
{
public string TeamName;
public int RunningTotal
}
但事实证明,指南指出你不应该继承List<T>
。 本指南在两方面让我感到十分困惑。
为什么不?
显然, List
以某种方式优化了性能。 怎么会这样? 如果我扩展List
会导致哪些性能问题? 什么会打破?
我看到的另一个原因是List
是由Microsoft提供的,我无法控制它,因此在公开“公共API”后我不能在以后更改它。 但我很难理解这一点。 什么是公共API,我为什么要关心? 如果我目前的项目没有,也不可能拥有这个公共API,我可以放心地忽略这个指南吗? 如果我从List
继承,事实证明我需要一个公共API,那么我会遇到什么困难?
为什么它甚至重要? 列表是一个列表。 什么可能改变? 我可能想要改变什么?
最后,如果微软不希望我继承List
,为什么他们没有把课程sealed
?
我还应该使用什么?
显然,对于自定义集合,Microsoft提供了一个应该扩展而不是List
的Collection
类。 但是这个类是非常AddRange
,并没有很多有用的东西,比如AddRange
。 jvitor83的答案提供了该特定方法的性能基本原理,但是如何缓慢的AddRange
不比没有AddRange
更好?
从Collection
继承比继承List
,我看不到任何好处。 毫无疑问,微软不会让我无缘无故地做额外的工作,所以我不禁感觉自己在某种程度上误解了某些东西,并且继承Collection
实际上并不是我的问题的正确解决方案。
我见过诸如实施IList
建议。 就是不行。 这是几十行样板代码,没有任何收获。
最后,有人建议将List
包装在一些东西中:
class FootballTeam
{
public List<FootballPlayer> Players;
}
这有两个问题:
它使我的代码不必要地冗长。 我现在必须调用my_team.Players.Count
而不仅仅是my_team.Count
。 值得庆幸的是,在C#中,我可以定义索引器来使索引变得透明,并且转发内部List
所有方法......但是这是很多代码! 我为这些工作得到什么?
它只是普通的没有任何意义。 一个足球队没有“拥有”一个球员名单。 这是球员的名单。 你不会说“John McFootballer加入了SomeTeam的球员”。 你说“约翰加入了SomeTeam”。 您不会为“字符串的字符”添加字母,而是将字母添加到字符串中。 你不会为图书馆的书籍添加书籍,而是向图书馆添加一本书。
我意识到,“引擎盖下”发生的事情可以说是“在X的内部列表中添加X”,但这似乎是一种非常直观的思考世界的方式。
我的问题(总结)
什么是代表一个数据结构,正确的C#的方式,其“逻辑”(即,“以人的心灵”)只是一个list
的things
有一些花俏?
从List<T>
继承始终是不可接受的? 什么时候可以接受? 为什么/为什么不? 在决定是否继承List<T>
时,程序员必须考虑什么?
这里有一些很好的答案。 我会给他们添加以下几点。
什么是正确的C#表示数据结构的方式,“逻辑地”(即,“对于人类的头脑”)仅仅是一串带有一些花里胡哨的东西?
请任何十位熟悉足球存在的非计算机程序员的人填写空白处:
A football team is a particular kind of _____
有没有人说过“有几个足球运动员名单”,或者他们都说“运动队”,“俱乐部”或“组织”? 你的观点是足球队是一种特殊的球员列表,只有你的人类思想和人类的思想。
List<T>
是一个机制。 足球队是一个业务对象 - 也就是说,一个对象代表了一些在程序业务领域的概念。 不要混合这些! 足球队是一种团队; 它有一个名册,一个名册是一个球员名单。 名册不是一种特殊的球员列表。 名单是一个球员名单。 因此,创建一个名为Roster
的属性是一个List<Player>
。 并且在你看到它的时候使它成为ReadOnlyList<Player>
,除非你相信每个了解足球队的人都会从名单中删除球员。
从List<T>
继承始终是不可接受的?
谁不能接受? 我? 没有。
什么时候可以接受?
在构建扩展List<T>
机制的机制时。
在决定是否继承List<T>
时,程序员必须考虑什么?
我是在建立一个机制还是一个商业对象?
但是这是很多代码! 我为这些工作得到什么?
你花了更多的时间输入你的问题,它会让你为List<T>
的相关成员编写50次转发方法。 你显然不怕冗长,而且我们在这里谈论的是非常少量的代码; 这是几分钟的工作。
UPDATE
我给了它更多的思考,还有另一个理由不模仿一个足球队作为球员名单。 事实上,将一个橄榄球队建模成球员名单也许是一个坏主意。 球队/球员名单的问题在于,你所得到的是球队在某个时刻的快照。 我不知道你们这个班的商业案例是什么,但是如果我有一个代表足球队的课程,我想问一些问题,比如“在2003年到2013年期间有多少海鹰队球员因伤缺席比赛?” 或者“之前效力于另一支球队的丹佛球员的场均跑步数量同比增幅最大?” 或者“这些猪人今年一路走来了吗?”
也就是说,足球队在我看来很好的模仿了一系列历史事实,例如当一名球员被招募,受伤,退役等等。显然,当前的球员名单是一个重要的事实,中心,但可能还有其他有趣的事情需要用更多的历史视角来处理。
最后,有人建议将List包装在一些东西中:
这是正确的方法。 “不必要的罗嗦”是一个不好的方式来看待这一点。 它在写my_team.Players.Count
时有明确的含义。 你想要统计球员。
my_team.Count
没有任何意义。 算什么?
一个团队不是一个清单 - 不仅仅是一个球员列表。 一个球队拥有球员,所以球员应该成为球员的一部分(一名成员)。
如果你真的担心它过于冗长,你可以随时暴露团队的属性:
public int PlayerCount {
get {
return Players.Count;
}
}
成为:
my_team.PlayerCount
这现在有意义并遵守得墨忒耳定律。
您还应该考虑遵守复合重用原则。 通过从List<T>
继承,你说的是一个团队是一个球员列表,并暴露出不必要的方法。 这是不正确的 - 正如你所说的,一个团队不仅仅是一个球员名单:它有一个名字,经理,董事会成员,培训师,医务人员,工资帽等等。通过让你的团队级别包含一个球员名单,你'说一支球队有一份球员名单',但它也可以有其他的东西。
哇,你的文章有很多问题和观点。 你从微软获得的大部分推理都是正确的。 让我们从关于List<T>
一切开始
List<T>
是高度优化。 它的主要用途是用作对象的私有成员。 class MyList<T, TX> : List<CustomObject<T, Something<TX>> { ... }
: class MyList<T, TX> : List<CustomObject<T, Something<TX>> { ... }
。 现在就像做var list = new MyList<int, string>();
。 IList<T>
。 这让你在稍后改变类的实现。 Collection<T>
非常通用,因为它是一个通用的概念......名字说明了一切; 它只是一个集合。 有更精确的版本,如SortedCollection<T>
, ObservableCollection<T>
, ReadOnlyCollection<T>
等,每个实现IList<T>
但不是 List<T>
。 Collection<T>
允许成员(即添加,删除等)被覆盖,因为它们是虚拟的。 List<T>
不。 如果我写这段代码,这个类可能看起来像这样:
public class FootballTeam
{
// Football team rosters are generally 53 total players.
private readonly List<T> _roster = new List<T>(53);
public IList<T> Roster
{
get { return _roster; }
}
// Yes. I used LINQ here. This is so I don't have to worry about
// _roster.Length vs _roster.Count vs anything else.
public int PlayerCount
{
get { return _roster.Count(); }
}
// Any additional members you want to expose/wrap.
}
链接地址: http://www.djcxy.com/p/1577.html