为什么 C# LinkedList.RemoveFirst() 不返回删除的值?
是否有一些惯用、性能或设计理念原因导致 C# 的 LinkedList 的 RemoveFirst() 和 RemoveLast() 操作不返回删除的值?
现在,如果我想读取并删除第一个值,我相信咒语是:
LinkedList<string> list = ...;
...
string removed = list.First.Value;
list.RemoveFirst();
在 Java 中,它将是:
LinkedList<String> list = ...;
...
String removed = list.removeFirst();
不要误会我的意思;我并不是想说 Java 更好。 C# 的 LinkedList 具有更多功能,只需将 Node 公开为公共构造即可。我试图理解设计选择。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我无法真正给出明确的答案,因为我无法理解
LinkedList
设计者的想法。我能说的是这样的。在 Java 中,
LinkedList
类实现Queue
接口,这反映了设计者的决定:“你知道吗?链表可以很容易用作队列,因此我们不妨让它实现该接口。”与队列交互的方式是从末尾弹出项目,然后,使用它们来做某事(这意味着对于Pop
类似操作返回弹出的元素)。在 .NET 中,没有
IQueue
接口。基本上,设计者做出了不同的决定:“我们所知道的类似队列行为的最有效实现是一个简单的基于数组的循环队列。因此,如果开发人员想要一个队列,他们应该使用Queue< /code> 类,就是这样。”
如果开发人员想要使用
LinkedList
作为队列(或双端队列),他/她很可能是为他/她实际需要的数据结构选择了错误的实现(从 .NET 的角度来看)。因此,本着“正确的函数应该只做一件事”的精神,BCL 人们选择让
LinkedList.RemoveFirst
做到这一点:删除第一个元素(类似于>List.RemoveAt
只是删除指定索引处的元素并且不返回任何内容)。我并不是说这个决定是对还是错。我认为 Java 和 .NET 中标准链表类的不同接口只是反映了对链表是什么以及如何在两个框架中使用的不同看法。
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 theQueue<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 aPop
-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 theQueue<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 howList<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.
程序员在删除第一个节点时可能并不总是希望返回它。如果
RemoveFirst
返回节点并且程序员不需要它,它仍然需要内存分配和处置。在我看来,可选择存储第一个节点(使用 First 属性)并拥有单独的删除函数似乎更灵活。The programmer may not always want to return the first node when removing it. If
RemoveFirst
returned the node and the programmer did not need it, it would still require memory allocation and disposal. Optionally storing the first node (using theFirst
property) and having a separate remove function seems more flexible, in my opinion.您是否考虑过使用 Queue 或 Stack 集合来代替 LinkedList?然后你可以推送和弹出并获得你想要的行为。
Have you considered using a Queue or a Stack collection instead of a LinkedList? you can then push and pop and get the behavior you desire.
RemoveFirst
和RemoveLast
实际上不返回值的原因是LinkedList
在内部将节点存储为LinkedListNode
T>
。LinkedListNode
对象具有Next
和Previous
的概念,但是如果从父集合中删除该对象,这些属性将指向哪里?The reason that
RemoveFirst
andRemoveLast
doesn't actually return the value is that internally theLinkedList<T>
stores nodes asLinkedListNode<T>
. TheLinkedListNode
object has a concept ofNext
andPrevious
but if you remove the object from the parent collection where would these properties point?