Почему С# LinkedList.RemoveFirst() возвращает удаленное значение?

Есть ли какая-то идиоматическая, функциональная или дизайнерская философия, почему С# LinkedList RemoveFirst() и RemoveLast() не возвращают значение?

Прямо сейчас, если я хочу прочитать и удалить первое значение, я считаю, что заклинание:

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

В Java это будет:

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

Не поймите меня неправильно; Я не пытаюсь сказать, что Java лучше. С# LinkedList имеет гораздо больше преимуществ, просто раскрывая Node как публичную конструкцию. Я пытаюсь понять варианты дизайна.

Ответ 1

Я не могу дать окончательного ответа, так как я не могу читать мысли дизайнеров LinkedList<T>. Я могу сказать это.

В Java класс LinkedList<E> реализует интерфейс Queue<E>, который отражает решение относительно части дизайнеров: "Вы знаете, что? Связанный список можно легко использовать в качестве очереди, поэтому мы могли бы также иметь он реализует этот интерфейс". И способ, которым вы взаимодействуете с очередью, заключается в том, чтобы вытаскивать элементы из конца, а затем, вы знаете, используя их для чего-то (что означает, что для операции Pop, возвращаемой элементом, вызывается естественным).

В .NET отсутствует интерфейс IQueue<T>. В принципе, дизайнеры приняли другое решение: "Самая эффективная реализация поведения в очереди, о котором мы знаем, представляет собой простую круглую очередь на основе массивов. Поэтому, если разработчикам нужна очередь, они должны использовать класс Queue<T>, который точно что".

Если разработчик хочет использовать LinkedList<T> в качестве очереди (или дека в этом отношении), скорее всего, он выбирает неправильную реализацию для структуры данных, которая им действительно нужна (из точки .NET).

Таким образом, в духе "правильная функция должна делать что-то одно", люди BCL решили сделать LinkedList<T>.RemoveFirst сделать именно это: удалить первый элемент (аналогично тому, как List<T>.RemoveAt просто удаляет элемент в указанный индекс и ничего не возвращает).

Я не говорю, что решение правильное или неправильное. Я думаю, что различные интерфейсы стандартного класса связанных списков в Java и .NET просто отражают разные представления о том, что такое связанный список, и как он должен использоваться в двух рамках.

Ответ 2

Программист не всегда может вернуть первый node при его удалении. Если RemoveFirst вернул node, и программисту это не понадобилось, все равно потребовалось бы выделение и удаление памяти. При желании сохранение первого node (с использованием свойства First) и наличие отдельной функции удаления кажется более гибким, на мой взгляд.

Ответ 3

Рассматривали ли вы использование очереди или коллекции стека вместо LinkedList? вы можете нажать и поп и получить желаемое поведение.

Ответ 4

Причина, по которой RemoveFirst и RemoveLast фактически не возвращает значение, заключается в том, что внутри LinkedList<T> хранит узлы как LinkedListNode<T>. Объект LinkedListNode имеет концепцию Next и Previous, но если вы удаляете объект из родительской коллекции, где бы эти свойства указывали?