Search code examples
c#collectionsapi-design

Why doesn't C# LinkedList.RemoveFirst() return the removed value?


Is there some idiomatic, performance or design philosophy reason why C#'s LinkedList's RemoveFirst() and RemoveLast() operations don't return the value removed?

Right now, if I want to read and remove the first value, I believe the incantation is:

LinkedList<string> list = ...;
...
string removed = list.First.Value;
list.RemoveFirst();

In Java, it would be:

LinkedList<String> list = ...;
...
String removed = list.removeFirst();

Don't get me wrong; I am not trying to say Java is better. C#'s LinkedList has many more affordances, simply by exposing the Node as a public construct. I am trying to understand the design choices.


Solution

  • I can't really give a definitive answer, as I can't read the minds of the designers of LinkedList<T>. What I can say is this.

    In Java, the LinkedList<E> class implements the Queue<E> interface, which reflects a decision on the designers' part: "You know what? A linked list can easily be used as a queue, so we might as well have it implement that interface." And the way you interact with a queue is by popping items off the end, and then, you know, using them for something (which means it's natural for a Pop-like operation to return the element popped).

    In .NET, there is no IQueue<T> interface. Basically, the designers made a different decision: "The most efficient implementation of queue-like behavior we know of is a simple array-based circular queue. So if developers want a queue, they should use the Queue<T> class, which is exactly that."

    If a developer wants to use a LinkedList<T> as a queue (or a deque for that matter), chances are he/she is picking the wrong implementation for the data structure he/she actually needs (from the .NET point of view).

    Thus, in the spirit of "a proper function should do exactly one thing," the BCL folks opted to make LinkedList<T>.RemoveFirst do just that: remove the first element (similar to how List<T>.RemoveAt just removes the element at the specified index and returns nothing).

    I'm not saying either decision is right or wrong. I think the different interfaces of the standard linked list class in Java and .NET simply reflect different views of what a linked list is and how it should be used within the two frameworks.