为何不从列表继承 ? - Why not inherit from List?

问题:

When planning out my programs, I often start with a chain of thought like so: 在计划程序时,我一般会像这样思考: 程序员

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. 该列表的顺序表明了在名单中列出球员的顺序。 数据结构

But I realize later that teams also have other properties, besides the mere list of players, that must be recorded. 可是后来我意识到,除了球员名单外,球队还有其余属性,必须加以记录。 For example, the running total of scores this season, the current budget, the uniform colors, a string representing the name of the team, etc.. 例如,本赛季的总得分,当前预算,统一的颜色,表明球队名称的string等。 app

So then I think: 因此我想: less

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 (an int ). 好的,一支足球队就像一个球员名单,可是另外,它还有一个名字( string )和总得分(一个int )。 .NET does not provide a class for storing football teams, so I will make my own class. .NET没有提供用于存储足球队的课程,所以我将建立本身的课程。 The most similar and relevant existing structure is List<FootballPlayer> , so I will inherit from it: 最类似和相关的现有结构是List<FootballPlayer> ,因此我将从它继承: ide

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

But it turns out that a guideline says you shouldn't inherit from List<T> . 但事实证实, 有一条准则规定您不该从List<T>继承 I'm thoroughly confused by this guideline in two respects. 我对该指南在两个方面彻底感到困惑。 性能

Why not? 为何不?

Apparently List is somehow optimized for performance . 显然List在某种程度上针对性能进行了优化 How so? 怎么会这样? What performance problems will I cause if I extend List ? 若是我扩展List会致使什么性能问题? What exactly will break? 到底会破裂什么? 优化

Another reason I've seen is that List is provided by Microsoft, and I have no control over it, so I cannot change it later, after exposing a "public API" . 我看到的另外一个缘由是List由Microsoft提供,而且我没法控制它,所以之后在公开“ public API”以后就没法更改它 But I struggle to understand this. 可是我很难理解这一点。 What is a public API and why should I care? 什么是公共API,我为何要关心? If my current project does not and is not likely to ever have this public API, can I safely ignore this guideline? 若是我当前的项目没有而且不太可能拥有此公共API,那么我能够安全地忽略此指南吗? If I do inherit from List and it turns out I need a public API, what difficulties will I have? 若是我确实从List继承而来但事实证实我须要一个公共API,我会遇到什么困难? ui

Why does it even matter? 为何如此重要? A list is a list. 列表就是列表。 What could possibly change? 有什么可能改变? What could I possibly want to change? 我可能要更改什么? this

And lastly, if Microsoft did not want me to inherit from List , why didn't they make the class sealed ? 最后,若是Microsoft不但愿我从List继承,他们为何不将类sealed

What else am I supposed to use? 我还应该使用什么?

Apparently, for custom collections, Microsoft has provided a Collection class which should be extended instead of List . 显然,对于自定义集合,Microsoft提供了Collection类,应该扩展该类而不是List But this class is very bare, and does not have many useful things, such as AddRange , for instance. 可是此类很是裸露,而且没有不少有用的东西, 例如AddRange jvitor83's answer provides a performance rationale for that particular method, but how is a slow AddRange not better than no AddRange ? jvitor83的答案提供了该特定方法的性能原理,可是慢速AddRange怎么比没有AddRange更好呢?

Inheriting from Collection is way more work than inheriting from List , and I see no benefit. Collection继承要比从List继承作更多的工做,我看不出任何好处。 Surely Microsoft wouldn't tell me to do extra work for no reason, so I can't help feeling like I am somehow misunderstanding something, and inheriting Collection is actually not the right solution for my problem. 固然,Microsoft不会平白无故地告诉我作额外的工做,所以我不由感到本身在某种程度上误解了某些东西,而继承Collection实际上不是解决我问题的正确方法。

I've seen suggestions such as implementing IList . 我已经看到了实现IList建议。 Just no. 就是不行。 This is dozens of lines of boilerplate code which gains me nothing. 这是几十行样板代码,对我毫无帮助。

Lastly, some suggest wrapping the List in something: 最后,有些人建议将List包装在如下内容中:

class FootballTeam 
{ 
    public List<FootballPlayer> Players; 
}

There are two problems with this: 这有两个问题:

  1. It makes my code needlessly verbose. 它使个人代码没必要要地冗长。 I must now call my_team.Players.Count instead of just my_team.Count . 我如今必须调用my_team.Players.Count而不是my_team.Count Thankfully, with C# I can define indexers to make indexing transparent, and forward all the methods of the internal List ... But that's a lot of code! 幸运的是,使用C#,我能够定义索引器以使索引透明化,并转发内部List全部方法...可是,这须要不少代码! What do I get for all that work? 我能从全部工做中获得什么?

  2. It just plain doesn't make any sense. 只是没有任何意义。 A football team doesn't "have" a list of players. 一支足球队没有“拥有”球员名单。 It is the list of players. 球员名单。 You don't say "John McFootballer has joined SomeTeam's players". 您不会说“ John McFootballer已加入SomeTeam的球员”。 You say "John has joined SomeTeam". 您说“约翰加入了SomeTeam”。 You don't add a letter to "a string's characters", you add a letter to a string. 您没有在“字符串的字符”中添加字母,而是在字符串中添加了字母。 You don't add a book to a library's books, you add a book to a library. 您没有将书添加到图书馆的书中,而是将书添加到图书馆。

I realize that what happens "under the hood" can be said to be "adding X to Y's internal list", but this seems like a very counter-intuitive way of thinking about the world. 我意识到,“幕后”发生的事情能够说是“将X添加到Y的内部列表中”,但这彷佛是一种很是反常的思考世界的方式。

My question (summarized) 个人问题(总结)

What is the correct C# way of representing a data structure, which, "logically" (that is to say, "to the human mind") is just a list of things with a few bells and whistles? 什么是C#表示数据结构的正确方法,“逻辑上”(也就是说,“对人类而言”)只是一小部分thingslist

Is inheriting from List<T> always unacceptable? List<T>继承始终是不可接受的吗? When is it acceptable? 何时能够接受? Why/why not? 为何/为何不呢? What must a programmer consider, when deciding whether to inherit from List<T> or not? 程序员在决定是否从List<T>继承时必须考虑什么?


解决方案:

参考一: https://stackoom.com/question/1T185/为何不从列表继承-T
参考二: https://oldbug.net/q/1T185/Why-not-inherit-from-List-T
相关文章
相关标签/搜索