我目前正在寻找自己的收藏品,这就像一个普通的清单,除了它只能容纳10件物品。如果在列表中已有10个项目时添加了项目,则在添加新项目之前将删除第一个项目。
我想要做的是创建一个扩展System.Collections.Generic.List<T>
的类,然后修改Add(T item)
方法以包含在必要时删除第一个项目的功能。
答案 0 :(得分:65)
您还可以通过
实现添加方法public new void Add(...)
在派生类中隐藏现有的添加并引入您的功能。
编辑:粗略轮廓......
class MyHappyList<T> : List<T>
{
public new void Add(T item)
{
if (Count > 9)
{
Remove(this[0]);
}
base.Add(item);
}
}
只是一个注释,认为它是隐含的,但您必须始终按实际类型引用您的自定义列表,而不是基本类型/接口,因为隐藏方法仅适用于您的类型和其他派生类型。
答案 1 :(得分:43)
首先,您不能覆盖Add并且仍然具有针对List的多态性,这意味着如果您使用new关键字并且您的类被强制转换为List,则不会调用您的新Add方法。 / p>
其次,我建议您查看Queue类,因为您要做的更多的是队列而不是列表。该类针对您想要做的事情进行了优化,但没有任何类型的大小限制器。
如果你真的希望某些东西像List一样工作但是像最大尺寸的Queue一样工作,我建议你实现IList并保留一个Queue实例来存储你的元素。
例如:
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
}
答案 2 :(得分:26)
您无法覆盖Add(),它不是虚方法。改为从IList派生并使用私有Queue成员进行实现。
答案 3 :(得分:17)
您可以扩展System.Collections.ObjectModel.Collection并覆盖InsertItem方法以获得所需的行为,并且它还实现了IList
答案 4 :(得分:8)
您可以编写一个实现IList<T>
的类,该类包含内部List<T>
并编写您自己的方法。
答案 5 :(得分:5)
我能做的最好就是:
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);
}
}
由于add()
方法未标记为虚拟。
答案 6 :(得分:3)
您对要求的描述听起来像Circular Buffer。
我实现了自己的 - 类似于this implementation on CodePlex,除了我的实现IList<T>
。
其他一些答案建议使用Queue<T>
- 但这并不完全相同,因为它只允许进行FIFO访问。
一般来说,不建议从List<T>
派生 - 而是从Collection<T>
派生,并实施您需要的任何其他内容。但是对于循环缓冲区,使用私有数组可能更合适,而不是像CodePlex实现那样从Collection<T>
派生。
答案 7 :(得分:1)
您可以查看C5集合库。它们具有ArrayList&lt; T&gt;。实现IList&lt; T&gt;并有一个虚拟的Add方法。 C5集合库是一个很棒的列表,队列,堆栈等集合......你可以在这里找到C5库:
答案 8 :(得分:1)
阅读Liskov Substitution Principle,您的收藏品是扩展列表<T>
的非常差的候选者,它甚至不是实施IList <T>
的绝佳选择。
此数据需要哪些读取模式?如果您只需要查看所有当前条目,那么实现IEnumerable <T>
和Add(T)方法应该足以开始。
然后可以通过私有队列(或者Deque会更好,但是这样的集合需要一些其他集合API,我不建议你自己尝试实现一个)来实现这一点,你在Add(Enqueue()期间将它排队()如果需要保持大小,可以使用Dequeue。
请注意,实现IEnumerable并提供Add方法意味着如果需要,您仍然可以使用Collection初始化语法。
如果您需要随机访问这些值,那么实现索引器可能是一个好主意,但如果没有更多关于该问题的上下文,我不会看到这会给您带来什么好处。
答案 9 :(得分:0)
您可以尝试扩展System.Collections.ObjectModel.Collection<T>
,这更加灵活。然后,您可以覆盖受保护的成员InsertItem
和SetItem
,以自定义集合的行为。
答案 10 :(得分:0)
如果使用显式接口实现,实际上是可以做到的。
public class SampleClass<T> : IList<T>
{
...
void IList<T>.Add(T item) { ... }
public int Add(T item) { ... }
...
}
然后调用,就像
IList<T> sample = new SampleClass();
int index = sample.Add(someStuffGoesHere); // new Add method is called