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> { }