The Lounge is rated Safe For Work. If you're about to post something inappropriate for a shared office environment, then don't post it. No ads, no abuse, and no programming questions. Trolling, (political, climate, religious or whatever) will result in your account being removed.
Have you noticed that a new house has the same house basic architecture and shape as all other houses previously built. A new car has the same architecture and basic shape as all other cars built. A new building has the same basic architecture and shape as all other buildings previously built. A new bridge has the same basic architecture and slightly varying shape as previously built bridges. But new software is different in its intended audiences and functions. Its architecture and shape will vary from product to product. Therefore it difficult to nail down specific engineering principles for software development.
I've implemented a list with circular buffer semantics meaning adding or removing from either end of the list is very efficient.
Because of this, the list can be efficiently used as a queue, a double ended queue, or a stack.
Well, right now I don't have any special methods to reflect the more efficient add and remove ops.
Doing an efficient add just means list.Add(item) for the end or list.Insert(0,item) for the beginning. Doing an efficient remove is similar with either list.RemoveAt(0) or list.RemoveAt(list.Count-1).
My question is this - should I add special methods for these efficient ops and if so what should they be?
I can go the .NET route that MS took and add methods like Enqueue() and Dequeue() (queue-like) but that only covers adding to the back, and removing from the front. I can add Pop() and Push() (stack-like) but that only covers adding and removing from the back. I can add both but that's cluttered and sill doesn't handle removing from the front.
Or I can take a page from C++/STL and add methods like PushFront() and PushBack() and similar remove methods, even though there's nothing in .NET like this.
Or I can just not add those extra methods and I can document the existing methods with the specially performing cases.
That was more of a mathematician's observation rather than a developper's one.
Naming the methods, though, is more of a preferences' question. It does not really matter provided their behaviour is clearly and unambiguously documented.
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
For the Circular part I would follow Microsofts convention on their LinkedList. (Which is Circular BTW, Reference Source[^] )
So AddBefore(), AddAfter(), AddFirst(), AddLast(), Remove(), RemoveFirst(), and RemoveLast().
But as soon as you treat it as a List, use the conventions of a list.
Have an Add and a Remove method, but add an overload for the special cases that uses an enum to control where it goes or comes from. Yes, it's a little less efficient (but a delegate table can help with that if the enum indexes into it) but it's a load easier to keep track of mentally than half a dozen or so Add methods.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
What you could do is add them as extension methods, either on your own (base-)class or interface or on IList<T>.
That way, you keep the base interface/implementation clean, while still offering utility methods that possibly extend to every implementation of your interface.
If you go that way, I'd recommend creating an ICircularList<T>, inherit from IList<T>, and add the extension methods there.
Or just add PushFront and PushBack, which is easy and straight-forward
I actually thought about doing that but I don't want to add them to standard list interfaces, just this one. I don't like putting inefficient methods on standard lists because it will encourage poor programming.
As far as adding them just to the CircularList that way, or creating ICircularList<t>, I don't really want the latter as I'd like to follow what microsoft has done (most of the time) with their list based data structures like Queue<T> and Stack<T> and just create the class itself. I can add extension methods, and I almost did, but the rest of my class is factored as partial classes - CircularList.cs, CircularList.ICollection.cs, CircularList.IList.cs, etc so I'll probably just add it like that.
I'm leaning toward PushFront/PopFront/PushBack/PopBack like STL, because it's also at least somewhat like Microsoft's pattern in .NET
I'm got an opinion. As far as I'm familiar with programming and algorithms, I think that for circular lists you still have to create your own non-generic class ICircularList<t> and implement a functionality for performing the most of circular lists operations. In this case, the using of the existing generic .NET collections is not efficient for that purpose, since it might come to be wasteful.
Here's a list of guidelines on how to implement circular lists:
First, it's not a linked list, circular or otherwise.
That would be a much different structure, with much different methods.
It's a circular buffer exposed as a IList<T>
Given your seeming confusion about that it might prompt me to rename though i'm not sure to what.
Because it's a circular buffer IList<T>, and ICollection<T> serve me fine. Sure you *can* call Insert(1, item) or RemoveAt(2) and that's not efficient, but it's no less efficient than doing it on a straight List<T> so I'm fine with it.