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

C# 为什么不从列表继承<;T>;?,c#,.net,list,oop,inheritance,C#,.net,List,Oop,Inheritance,在规划我的计划时,我通常会从这样的一系列想法开始: 足球队就是足球运动员的名单。因此,我应该用以下方式来表示: var football_team = new List<FootballPlayer>(); 但事实证明。我完全被这条指导方针搞糊涂了 为什么不呢? 显然。为什么呢如果扩展列表,会导致哪些性能问题?到底什么东西会断裂 我看到的另一个原因是List是由Microsoft提供的,我无法控制它,所以。但我很难理解这一点。什么是公共API?我为什么要关心它?如果我当前的项目没有

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

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

var football_team = new List<FootballPlayer>();
但事实证明。我完全被这条指导方针搞糊涂了

为什么不呢? 显然。为什么呢如果扩展
列表
,会导致哪些性能问题?到底什么东西会断裂

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

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

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

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

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

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

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

class FootballTeam 
{ 
    public List<FootballPlayer> Players; 
}
class足球队
{ 
公开球员名单;
}
这有两个问题:

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

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

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

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


    列表继承总是不可接受的吗?什么时候可以接受?为什么?程序员在考虑是否要从<代码>清单>代码>继承时必须考虑什么?

    首先,它与可用性有关。如果使用继承,则

    团队
    类将公开纯粹为对象操作而设计的行为(方法)。例如,
    AsReadOnly()
    CopyTo(obj)
    方法对团队对象没有意义。您可能需要更具描述性的
    AddPlayers(players)
    方法,而不是
    AddRange(items)
    方法

    如果您想使用LINQ,实现一个通用接口,如
    ICollection
    IEnumerable
    ,将更有意义


    如前所述,写作是正确的方法。只需实现一个玩家列表作为一个私有变量。

    哇,你的帖子有一大堆问题和观点。你从微软得到的大部分理由都是正确的。让我们从
    List

    • 列表
      经过高度优化。它的主要用途是用作对象的私有成员

    • Microsoft没有密封它,因为有时您可能希望创建一个名称更友好的类:
      class MyList:List这里有一些很好的答案。我想补充以下几点

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

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

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

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

      List
      是一种机制。Football team是一个业务对象——也就是说,一个表示程序的业务领域中的某个概念的对象。别把它们混在一起!足球队是一种球队;它有一个花名册,花名册是一份球员名单。名册并不是一份特殊的球员名单。名册是一份球员名单。因此,创建一个名为
      花名册
      的属性,它是一个
      列表
      。当你在做的时候,让它成为一个
      ReadOnlyList
      ,除非你相信每个了解足球队的人都可以从名册中删除球员

      class FootballTeam 
      { 
          public List<FootballPlayer> Players; 
      }
      
      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.
      }
      
      IList<Player> footballTeam = ...
      
      type FootballTeam = IList<Player>
      
      class FootballTeam : List<FootballPlayer> 
      { 
          public string TeamName; 
          public int RunningTotal;
      }
      
      public class FootballTeam
      {
          // A team's name
          public string TeamName; 
      
          // Football team rosters are generally 53 total players.
          private readonly List<T> _roster = new List<T>(53);
      
          public IList<T> Roster
          {
              get { return _roster; }
          }
      
          public int PlayerCount
          {
              get { return _roster.Count(); }
          }
      
          // Any additional members you want to expose/wrap.
      }
      
      class FootballTeam : List<FootballPlayer> 
      { 
          public string TeamName; 
          public int RunningTotal 
      }
      
      class FootballTeam 
      { 
          public List<FootballPlayer> players
          public string TeamName; 
          public int RunningTotal 
      }
      
      myTeam.subList(3, 5);
      
      class FootballTeam : ... ICollection<Player>
      {
          ...
      }
      
      class FootballTeam ...
      {
          public ICollection<Player> Players { get { ... } }
      }
      
      class FootballTeam : ... ICollection<Player>, 
                               ICollection<StaffMember>,
                               ICollection<Score>
      {
          ....
      }
      
      class FootballTeam
      {
          List<FootballPlayer> Players { get; set; }
          List<FootballPlayer> ReservePlayers { get; set; }
      }
      
      class FootballTeam : List<FootballPlayer> 
      { 
          public string TeamName; 
          public int RunningTotal 
      }
      
      class FootballTeam
      {
          List<FootballPlayer> Players { get; set; }
          List<FootballPlayer> ReservePlayers { get; set; }
          List<FootballPlayer> RetiredPlayers { get; set; }
      }
      
      team.Players.ByName("Nicolas")
      
      team.ByName("Nicolas")
      
      club.Players.ByName("Nicolas")
      
      team.Players.ByName("Nicolas") 
      
      team.ByName("Nicolas")
      
      string team = new string();
      
       class FootballTeam : List<FootballPlayer> {
           override void Add(FootballPlayer player) {
              if (this.Sum(p => p.Salary) + player.Salary > SALARY_CAP)) {
                throw new InvalidOperationException("Would exceed salary cap!");
              }
           }
       }
      
       class FootballTeam : IList<FootballPlayer> {
           private List<FootballPlayer> Players { get; set; }
      
           override void Add(FootballPlayer player) {
              if (this.Players.Sum(p => p.Salary) + player.Salary > SALARY_CAP)) {
                throw new InvalidOperationException("Would exceed salary cap!");
              }
           }
           /* boiler plate for rest of IList */
       }
      
      public class PlayerCollection : Collection<Player> 
      { 
      }
      
      public class FootballTeam 
      { 
          public string Name { get; set; }
          public string Location { get; set; }
      
          public ManagementCollection Management { get; protected set; } = new ManagementCollection();
      
          public CoachingCollection CoachingCrew { get; protected set; } = new CoachingCollection();
      
          public PlayerCollection Players { get; protected set; } = new PlayerCollection();
      }
      
      class Team : IEnumerable<Player>
      {
          private readonly List<Player> playerList;
      
          public Team()
          {
              playerList = new List<Player>();
          }
      
          public Enumerator GetEnumerator()
          {
              return playerList.GetEnumerator();
          }
      
          ...
      }
      
      class Player
      {
          ...
      }
      
      public class DemoList : List<Demo>
      {
          // using XmlSerializer this properties won't be seralized
          // There is no error, the data is simply not there.
          string AnyPropertyInDerivedFromList { get; set; }     
      }
      
      public class Demo
      {
          // this properties will be seralized
          string AnyPropetyInDemo { get; set; }  
      }
      
      public interface IMoreConvenientListInterface<T> : IList<T>
      {
          void AddRange(IEnumerable<T> collection);
      }
      
      public class MoreConvenientList<T> : List<T>, IMoreConvenientListInterface<T> { }