如何覆盖列表<;T>';s在C#中添加方法?
我目前正在寻找我自己的收集,这将就像一个普通的名单,除了它将只容纳10个项目。如果在列表中已有10个项目时添加了一个项目,那么在添加新项目之前,第一个项目将被删除如何覆盖列表<;T>';s在C#中添加方法?,c#,generics,inheritance,collections,C#,Generics,Inheritance,Collections,我目前正在寻找我自己的收集,这将就像一个普通的名单,除了它将只容纳10个项目。如果在列表中已有10个项目时添加了一个项目,那么在添加新项目之前,第一个项目将被删除 我想做的是创建一个扩展System.Collections.Generic.List的类,然后修改Add(T item)方法,以包含必要时删除第一项的功能。您不能重写Add(),它不是虚拟方法。改为从IList派生并使用专用队列成员进行实现。您只需编写一个实现IList的类,该类包含一个内部的列表,并编写自己的方法。您还可以通过 pu
我想做的是创建一个扩展
System.Collections.Generic.List
的类,然后修改Add(T item)
方法,以包含必要时删除第一项的功能。您不能重写Add(),它不是虚拟方法。改为从IList派生并使用专用队列成员进行实现。您只需编写一个实现IList的类,该类包含一个内部的列表,并编写自己的方法。您还可以通过
public new void Add(...)
在派生类中隐藏现有的添加和介绍功能
编辑:粗略的轮廓
class MyHappyList<T> : List<T>
{
public new void Add(T item)
{
if (Count > 9)
{
Remove(this[0]);
}
base.Add(item);
}
}
类MyHappyList:列表
{
新增公共作废(T项)
{
如果(计数>9)
{
删除(此[0]);
}
基础。添加(项目);
}
}
只是一个注释,我认为这是隐含的,但您必须始终按实际类型引用自定义列表,而决不能按基类型/接口引用,因为隐藏方法仅适用于您的类型和其他派生类型。似乎我能做的最好的事是:
class MostRecentList<T> : System.Collections.Generic.List<T> {
private int capacity;
public MostRecentList(int capacity) : base() {
this.capacity = capacity;
}
public new void Add(T item) {
if (base.Count == capacity) {
base.RemoveAt(0);
}
base.Add(item);
}
}
类MostRecentList:System.Collections.Generic.List{
私人int能力;
公共MOST中心列表(内部容量):基本(){
这个。容量=容量;
}
新增公共作废(T项){
if(base.Count==容量){
基。移除(0);
}
基础。添加(项目);
}
}
由于add()
方法没有标记为virtual。首先,您不能覆盖add,并且仍然具有针对的多态性,这意味着如果您使用new关键字并且将类强制转换为列表,则不会调用新的add方法
其次,我建议你深入课堂,因为你要做的更多的是一个队列而不是一个列表。该类针对您想要做的事情进行了优化,但没有任何类型的大小限制
如果您真的希望某些东西像列表一样工作,但像最大大小的队列一样工作,我建议您实现并保留一个队列实例来存储元素
例如:
public class LimitedQueue<T> : IList<T>
{
public int MaxSize {get; set;}
private Queue<T> Items = new Queue<T>();
public void Add(T item)
{
Items.Enqueue(item);
if(Items.Count == MaxSize)
{
Items.Dequeue();
}
}
// I'll let you do the rest
}
公共类受限队列:IList
{
public int MaxSize{get;set;}
专用队列项目=新队列();
公共作废新增(T项)
{
项目。排队(项目);
如果(Items.Count==MaxSize)
{
Items.Dequeue();
}
}
//剩下的我让你来做
}
您可以查看C5集合库。它们有一个实现IList的ArrayList和一个虚拟Add方法。C5集合库是一个非常棒的列表、队列、堆栈等集合。。。您可以在此处找到C5库:
请阅读,您的集合对于扩展列表来说是一个非常糟糕的候选者,它甚至不是实现IList
的理想候选者
此数据需要什么读取模式?如果只需要查看所有当前条目,那么实现IEnumerable
和Add(T)方法就足够了
然后可以通过一个私有队列(或者Deque会更好,但这样的集合需要一些其他集合API,我不建议您自己尝试实现),在添加过程中将其放入队列()(如果需要保持大小,可以使用Dequeue)
请注意,实现IEnumerable并提供Add方法意味着您仍然可以在需要时使用集合初始化器语法
如果您需要随机访问这些值,那么实现索引器可能是一个好主意,但如果没有更多关于这个问题的上下文,我看不出这会给您带来什么好处。您可以扩展并覆盖InsertItem方法以获得所需的行为,它还实现了IList您对需求的描述听起来像是一个简单的例子
我实现了自己的-与类似,只是我的实现了IList
其他一些答案建议使用队列
——但这不是一回事,因为它只允许FIFO访问
一般来说,不建议从列表
派生,而是从集合
派生,并实现您需要的任何其他内容。但是对于循环缓冲区,可能更适合使用私有数组,而不是像CodePlex实现那样从集合
派生。您可以尝试扩展System.Collections.ObjectModel.Collection
,它更灵活。然后,您可以覆盖受保护的成员InsertItem
和SetItem
,以自定义集合的行为。我同意,我认为队列是这种情况下的最佳选择。请记住,我建议的代码决不是线程安全的。你必须自己做这件事。:)@昆汀:的确,我同意,先生。“就像一个普通的列表,除了它只能容纳10个项目”听起来更像是一个循环缓冲区,而不是一个队列。请看我的答案。这是一个非常糟糕的想法,根据用于发送Add消息的变量类型,您的类的行为不再正确。实际上,您需要仔细阅读LSP及其描述的可替换性。请记住,如果使用此方法,如果将类转换为列表,则该类将无法工作。您的新Add方法将永远不会被调用。你真的应该考虑使用一个队列。@ ShuggyCoUk LSP意味着什么?收藏不允许我重写Addit。显然,当我打算投票时,我否决了这一点,现在就意识到,我不能改变它: