I am working in .Net environment using C#. I need some alternative for the Stack data structure. Some kind of bound stack. The quantity of elements in the collection shouldn't exceed some fixed specified number. And, if that number achieved and new element is pushed, than most older element must be deleted. I need this for storing commands for Undo/Redo strategies.
5 Answers
A circular buffer should do the job; easy enough to wrap a list or array, but nothing built in AFAIK.

- 1,026,079
- 266
- 2,566
- 2,900
-
2Thank you. I found free implementation of the circular buffer here: bufferhttp://circularbuffer.codeplex.com/ – Peter17 Feb 15 '11 at 12:17
Johnny Coder has an implementation here: http://johnnycoder.com/blog/2008/01/07/undo-functionality-with-a-limited-stack/

- 14,520
- 6
- 56
- 80
This is an implementation of a stack with a constrained capacity. After reaching the given capacity, bottom items of the stack beyond the capacity are discarded. It is possible to iterate through the contained objects and set the index to a specifc position (like a rewind) for discarding multiple entries at once when pushing a new item to the stack.
This is an own implementation with some goodies that prevents you from handling more then one list if you need to go back in the history and forward again (is builtin).
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();
}
}
Anyway, building a stack that discards elements when the maximum capacity is reached should be implemented using a LinkedList (as suggested above) if your list is huge (avoids copying). So the LinkedList idea might be better in such a case instead of wrapping a List if the buffer maximum is a high value.
I would also recommend to pack the Push(), Pop() etc. into an interface (e.g. IStack). Sadly, there is no IStack interface predefined in .Net (afaik).

- 7,685
- 6
- 52
- 94
.Net is rather deficient in type of collections. You'll find a collection library here. Use CircularQueue.

- 2,111
- 11
- 13
-
Thank you. Collection library will be handy. Now I know where to look when I need some specific collection. – Peter17 Feb 15 '11 at 12:42
There's no builtin Class for this in Framework. (we dont expect to delete data automatically). But you can very well Extend the Stack class and Override Push/Pop and other Methods to suit your needs.

- 18,056
- 9
- 55
- 79
-
This is not a good idea because they are not virtual. You could downcast and the old Methods get called. – Beachwalker Oct 03 '12 at 21:48
-
When you down cast It obviously mean you want the base implementation... and that's what it should be.. – Shekhar_Pro Oct 05 '12 at 07:22
-
The problem is that there is no IStack
interface. It is "safer" to embed the list as member in this case (composition instead of inheritance). Otherwise inheritance could lead to unexpected results. What if someone calls Push() of the downcasted System.Collections.Generics.Stack – Beachwalker Oct 05 '12 at 07:41and your public new Push() implementation should fire an event... the event is NOT fired and the listeners don't get the info about the stack change (e.g. when showing the number of items).