简体   繁体   English

为什么LinkedList(T)没有实现IList(T)接口?

[英]Why doesn't LinkedList(T) implement the IList(T) interface?

In C#, the LinkedList(T) class does not implement the IList(T) interface. 在C#中,LinkedList(T)类不实现IList(T)接口。 However, the List(T) class does implement IList(T). 但是,List(T)类确实实现了IList(T)。 Why is there this discrepancy? 为什么会出现这种差异? Functionally, they are both lists, so this design choice seems odd. 从功能上讲,它们都是列表,所以这个设计选择看起来很奇怪。 It now becomes difficult to switch implementations from List(T) to LinkedList(T). 现在很难将实现从List(T)切换到LinkedList(T)。

IList<T> interface contains an indexer, the indexer is not a functionality you expect on a LinkedList . IList<T>接口包含索引器,索引器不是您在LinkedList上预期的功能。

List<T> can assure access to items in O(1) , LinkedList by definition of it's it structure can't provide access to items in O(1) . List<T>可以确保通过定义来访问O(1)LinkedList的项目,它的结构不能提供对O(1)中项目的访问。

See the definition of a linked list , and you will understand. 查看链接列表的定义,您将理解。

Main issue, LinkedLists can contain circular references, and thus does not have an index. 主要问题,LinkedLists可以包含循环引用,因此没有索引。

Linked lists are among the simplest and most common data structures; 链表是最简单和最常见的数据结构之一; they provide an easy implementation for several important abstract data structures, including stacks, queues, associative arrays, and symbolic expressions. 它们为几个重要的抽象数据结构提供了简单的实现,包括堆栈,队列,关联数组和符号表达式。

The principal benefit of a linked list over a conventional array is that the order of the linked items may be different from the order that the data items are stored in memory or on disk. 链接列表相对于传统阵列的主要好处是链接项的顺序可能与数据项存储在内存或磁盘上的顺序不同。 For that reason, linked lists allow insertion and removal of nodes at any point in the list, with a constant number of operations. 因此,链接列表允许在列表中的任何位置插入和删除节点,并且操作数量恒定。

On the other hand, linked lists by themselves do not allow random access to the data, or any form of efficient indexing. 另一方面,链表本身不允许随机访问数据或任何形式的有效索引。 Thus, many basic operations — such as obtaining the last node of the list, or finding a node that contains a given datum, or locating the place where a new node should be inserted — may require scanning most of the list elements. 因此,许多基本操作 - 例如获取列表的最后一个节点,或找到包含给定数据的节点,或定位应插入新节点的位置 - 可能需要扫描大多数列表元素。

There are three types of guarantee given by an interface, 1 programmatic and 2 conceptual. 接口给出了三种类型的保证,1种是程序性的,2种是概念性的。

The programmatic guarantee is that you can call a method or property that exists. 程序保证是您可以调用存在的方法或属性。 .NET enforces this guarantee. .NET强制执行此保证。

The first conceptual guarantee is that it will work. 第一个概念保证是它会起作用。 This is often broken (NotImplementedException and NotSupportedException exist precisely to break this) but there should be a good reason for doing this. 这经常被破坏(NotImplementedException和NotSupportedException正好存在以打破这个),但应该有一个很好的理由这样做。 Still, it's more a promise than a guarantee. 不过,这更像是承诺而非保证。

The second conceptual guarantee is also more a promise than a guarantee, which is that the method or property will work much like other cases. 第二个概念保证也是承诺而不是保证,即方法或财产将像其他情况一样工作。

People are used to getting on an IList's indexer working in reasonably fast - O(1) or at worse about O(log n) - and breaking that conceptual promise will lead to people using your object badly. 人们习惯于让IList的索引器以相当快的速度运行 - O(1)或更糟糕的O(log n) - 并打破这个概念上的承诺会导致人们严重使用你的对象。

There's no concrete rule here. 这里没有具体的规则。 You certainly can implement IList as a linked list, and suffer the O(n) indexed get. 您当然可以将IList实现为链接列表,并且遭受O(n)索引获取。 You can also implement a linked list in such a way that it doesn't keep a record of its count (as that supplied by the framework does) and have an O(n) Count property. 您还可以实现链接列表,使其不保留其计数记录(由框架提供的记录)并具有O(n)Count属性。 But then people are more likely to use it badly. 但是人们更有可能使用它。

Part of component design is not just making sure things work and work well, but guiding their use. 组件设计的一部分不仅仅是确保工作正常并且运行良好,而是指导它们的使用。 A linked list that implements IList would fail at the latter point, and hence one could make a strong argument that it would not be as good a design as that offered. 实现IList的链表在后一点会失败,因此人们可以提出一个强有力的论据,即它不会像提供的那样好。

LinkedList is actually a widely-known list data structure which has following operation complexity: LinkedList实际上是一个众所周知的列表数据结构,具有以下操作复杂性:

Insertion: O(N)

Removal: O(1)

Indexing: O(N)

Whereas List is a continuos array, which has following algorithm complexity: 而List是一个连续数组,具有以下算法复杂性:

Insertion*: O(1)

Removal*: O(N)

Indexing: O(1)

They do not provide the common interface, cause it will misguide users of the interface and make programs efficiency unpredictable. 它们不提供通用接口,因为它会误导接口的用户并使程序效率变得不可预测。 For more information check out books on algorithms and data structures. 有关更多信息,请查看有关算法和数据结构的书籍。

The LinkedList is not a List. LinkedList不是List。 Lists are singular dimensional collections of objects. 列表是对象的单个维度集合。 A LinkedList is a node collection, more closely aligned with a Dictionary. LinkedList是一个节点集合,与Dictionary更紧密地对齐。 Its needs are not similar to a regular List but more specialized to allow for the node traversal and organization behaviors. 它的需求与常规List不相似,但更专业于允许节点遍历和组织行为。

This caught me by surprise as well.. Traditionally, a list is just something where you can depend on the order of the elements, and a linked list obeys this, and it should implement IList rather than ICollection (a collection does not say anything about the order of its elements). 这也让我感到意外。传统上,列表只是你可以依赖元素顺序的东西,链表遵循这个,它应该实现IList而不是ICollection(一个集合没有说什么关于其元素的顺序)。

Not implementing IList because some operations have poorer complexity than what some people would expect, is wrong in my opinion. 由于某些操作的复杂程度低于某些人的预期,因此我没有实现IList,这在我看来是错误的。

A "List" is data structure terms is not a linked list; “列表”是数据结构术语不是链表; it's actually an array -- List item are directly accessible, using the indexer, which is not available (not practical) in a linked list. 它实际上是一个数组 - 使用索引器可以直接访问列表项,索引器在链表中不可用(不实用)。

Historical quirk: in .NET 1.1 an ArrayList was the class that acts like a dynamic length array. 历史怪癖:在.NET 1.1中,ArrayList是一个类似于动态长度数组的类。

In .NET 2+ still, List internally organizes as an array. 在.NET 2+中,List内部组织为一个数组。 This means that IList expects Array semantics, really. 这意味着IList确实需要Array语义。

In .NET, Lists are like arrays , not lists.... (boing) 在.NET中,列表就像数组 ,而不是列表.... (boing)

True linked lists have constant time insertion, deletion, but slow enumeration and slower random access. 真正的链接列表具有恒定的时间插入,删除,但缓慢的枚举和较慢的随机访问。

Arrays have quick enumeration and random access, but have costly insertion / deletion (O(n) and reallocation can quicly lead to completely different behaviour) 数组具有快速枚举和随机访问,但具有昂贵的插入/删除(O(n)和重新分配可能会导致完全不同的行为)

因为通过索引访问链表不是O(1)。

A linked list is not a data structure that is designed to be accessed by index, however, IList<T> provides index access capabilities. 链表不是设计为由索引访问的数据结构,但IList<T>提供索引访问功能。

So, as you can't access items in a linked list by index, you can't provide methods that try to do that. 因此,由于您无法通过索引访问链接列表中的项目,因此无法提供尝试执行此操作的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM