6

I'm looking to add a "recently opened" functionality to my application, and was wondering if there was a simple built in way to do lists that "overflow". By this I mean, when you add an element beyond the capacity of the list, all the items are shifted.

Code example of desired functionality (obviously its not true, the list would actually contain A,B,C):

List<string> list = new List<string>();

//if Overflow was 2

list.Add("A");
list.Add("B");
//List now contains A,B
list.Add("C");
//List now contains B,C

Sorry for the simple question. The problem itself is obvious to solve (intail plan was to inherit from List), I just don't like having to re-invent the wheel and confuse future programmers with custom objects when the language or framework has that functionality.

James
  • 2,445
  • 2
  • 25
  • 35
  • 5
    First of all, `List` or any of the other data structures are *.NET* data structures, not *C#* data structures, but no, .NET has no such built-in data structure that will do *all* of that automatically. You can, however, use either a `Queue` or a `LinkedList` and some extra code to remove extra items once you reach the limit. – Lasse V. Karlsen Nov 25 '11 at 20:09
  • Like @LasseV.Karlsen said there is not such a thing, but you can inherit from a list or queue to make your own class that works the way you want. It is not so hard this way. – Hossein Nov 25 '11 at 20:13
  • 1
    Similar question: http://stackoverflow.com/questions/1213317/maximum-capacity-collection-in-c-sharp – Gerard Nov 25 '11 at 20:16
  • 2
    You might want to search on "circular buffer" / "ring buffer" – Marc Gravell Nov 25 '11 at 20:29

3 Answers3

5

As far as I know ther is no such collection in the library.
You can write this very easily, based on a List<> or an array.

// untested
class OverFlowList<T>
{
    T[] _data;
    int _next = 0;

    public OferflowList(int limit)
    {
        _data = new T[limit];
    }

    void Add(T item)
    {
        _data[_next] = item;
        _next = (_next + 1) % _data.Length;
    }    
}
H H
  • 263,252
  • 30
  • 330
  • 514
  • 1
    Don't you think inheriting from the built-in list is safer and easier to manage? – Hossein Nov 25 '11 at 20:14
  • 2
    @Hossein It isn't a good idea to inherit from the built in lists. They don't have virtual members, so a simple cast and your logic is gone. – Yuriy Faktorovich Nov 25 '11 at 20:15
  • 1
    @Henk that's an intersting idea. I'd add an iterator to get the items out in the correct order. – Yuriy Faktorovich Nov 25 '11 at 20:16
  • 1
    @Hossein I think implementing `ICollection` (or possibly `IList` if index-based access is important) would make a lot of sense. Inheriting from the `List` class itself (or `Queue` or whatever) would be way more work and possibly dangerous, as Yuriy points out. – dlev Nov 25 '11 at 20:16
  • 1
    Agreed that it's a bad idea to descend from `List`, but you could descend from `Collection`, which *is* meant to be inherited, and has all the virtual methods you need. – Joe White Nov 25 '11 at 20:24
4

You can do this easily with LinkedList<T>:

LinkedList<string> list = new LinkedList<string>();

//if Overflow was 2
list.AddFirst("A");
list.AddFirst("B");
list.AddFirst("C");
list.RemoveLast();

I would, personally, wrap this into a class that you could use, ie:

public class OverflowCollection<T> : IEnumerable<T>
{
    private int max;
    private LinkedList<T> list = new LinkedList<T>();

    public OverflowCollection(int maxItems)
    {
        this.max = maxItems;
    }

    public void Add(T item)
    {
        this.list.AddFirst(item);
        if (this.list.Count > max)
           this.list.RemoveLast();
    }

    // Implement IEnumerable<T> by returning list's enumerator...
}

This provides a very simple method, which has some nice advantages, including being able to change the overload amount at runtime, etc..

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
0

Use a custom class that implement IList then when implement Add method check your constraint and do it.

Reza ArabQaeni
  • 4,848
  • 27
  • 46