但是后来我意识到,团队除了球员名单之外还有其他属性需要记录。例如,本赛季的得分总和、当前预算、队服颜色、代表团队名称的字符串等等。 于是我想:A football team is just a list of football players. Therefore, I should represent it with:
var football_team = new List<FootballPlayer>();
The ordering of this list represent the order in which the players are listed in the roster.
Okay, a football team is just like a list of players, but additionally, it has a name (a
string
) and a running total of scores (anint
). .NET does not provide a class for storing football teams, so I will make my own class. The most similar and relevant existing structure isList<FootballPlayer>
, so I will inherit from it:class FootballTeam : List<FootballPlayer> { public string TeamName; public int RunningTotal }
但事实证明指南表明你不应该继承List<T>
。我对这个指南有两个方面感到彻底困惑。
为什么不行?
显然List
在性能上进行了优化。是怎样的优化?如果我扩展List
会导致什么性能问题?具体会出现什么问题?
另一个原因是,List
由Microsoft提供,我无法控制它,所以在公开API之后我不能更改它。但我很难理解这一点。什么是公开API,我为什么要关心它?如果我的当前项目没有并且不太可能有这种公开API,我可以安全地忽略这个指南吗?如果我继承了List
,然后事实证明我需要一个公开API,我会遇到什么困难?
为什么这很重要?列表就是列表,有什么可能会改变呢?我可能想要改变什么呢?
最后,如果微软不希望我从List
继承,那为什么不把这个类设为sealed
呢?
我还能用什么?
显然,对于自定义集合,微软提供了一个Collection
类,应该扩展它而不是List
。但这个类非常简单,没有很多有用的东西,例如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 的球员"。你会说 "John 加入了 SomeTeam"。你不会将一个字母添加到 "字符串的字符" 中,你会将一个字母添加到字符串中。你不会将一本书添加到图书馆的书中,你会将一本书添加到图书馆中。
things
列表?
从List<T>
继承是否总是不可接受的?它何时是可以接受的?为什么/为什么不?当决定是否继承List<T>
时,程序员必须考虑什么?