This is a limited capacity stack implementation. Having reached the specified capacity, the lower elements of the stack exceed the capacity. You can iterate over the contained objects and set the index to a position (for example, rewind) to drop several records at the same time when a new item is pushed onto the stack.
This is its own implementation with some goodies, which prevents you from processing more than one list if you need to go back in history and forward again (built-in).
public class DiscardingStack<TObject> : IEnumerable<TObject> { private readonly int capacity; private readonly List<TObject> items; private int index = -1; public DiscardingStack(int capacity) { this.capacity = capacity; items = new List<TObject>(capacity); } public DiscardingStack(int capacity, IEnumerable<TObject> collection) : this(capacity) { foreach (var o in collection) { Push(o); } } public DiscardingStack(ICollection<TObject> collection) : this(collection.Count, collection) { } public void Clear() { if (items.Count >= 0) { items.Clear(); index = items.Count - 1; } } public int Index { get { return index; } set { if (index >= 0 && index < items.Count) { index = value; } else throw new InvalidOperationException(); } } public int Count { get { return items.Count; } } public TObject Current { get { return items[index]; } set { index = items.IndexOf(value); } } public int Capacity { get { return capacity; } } public TObject Pop() { if (items.Count <= 0) throw new InvalidOperationException(); var i = items.Count - 1; var removed = items[i]; items.RemoveAt(i); if (index > i) index = i; return removed; } public void Push(TObject item) { if (index == capacity - 1) { items.RemoveAt(0); index--; } else if (index < items.Count - 1) { var removeAt = index + 1; var removeCount = items.Count - removeAt; items.RemoveRange(removeAt, removeCount); } items.Add(item); index = items.Count - 1; } public TObject Peek() { return items[items.Count-1]; } public TObject this[int i] { get { return items[i]; } } public IEnumerator<TObject> GetEnumerator() { return items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
In any case, creating a stack that discards items when it reaches maximum capacity should be implemented using LinkedList (as suggested above) if your list is huge (avoids copying). Thus, the idea of ββLinkedList might be better in this case instead of wrapping the list if the maximum buffer is a high value.
I also recommend packing Push (), Pop (), etc. to the interface (e.g. IStack). Unfortunately, there is no IStack interface predefined in .Net (afaik).
Beachwalker
source share