在C#中,LinkedList(T)类不实现IList(T)接口。但是,List(T)类确实实现了IList(T)。为什么会出现这种差异?从功能上讲,它们都是列表,所以这个设计选择看起来很奇怪。现在很难将实现从List(T)切换到LinkedList(T)。
答案 0 :(得分:27)
IList<T>
界面包含一个索引器,索引器不是您在LinkedList
上所期望的功能。
List<T>
可以确保访问 O(1),LinkedList
中的项目,因为它的结构不能提供对 O中项目的访问权限( 1)
答案 1 :(得分:11)
查看linked list的定义,您将理解。
主要问题,LinkedLists可以包含循环引用,因此没有索引。
链接列表是最简单的 和最常见的数据结构;他们 提供一个简单的实现 几个重要的抽象数据 结构,包括堆栈,队列, 关联数组和符号 表达式。
链表的主要好处 超过传统的阵列是 链接项目的顺序可能是 不同于数据的顺序 项目存储在内存或磁盘上。 因此,链表允许 插入和删除任何节点 列表中的一个常量 操作次数。
另一方面,链表由 他们自己不允许随机访问 数据,或任何形式的有效 索引。因此,许多基本操作 - 例如获取最后一个节点 列表,或找到一个节点 包含给定的数据或定位 应该是新节点的位置 插入 - 可能需要扫描最多 列表元素。
答案 2 :(得分:3)
接口提供三种类型的保证,1种是程序性的,2种是概念性的。
程序保证是您可以调用存在的方法或属性。 .NET强制执行此保证。
第一个概念保证是它会起作用。这经常被破坏(NotImplementedException和NotSupportedException正好存在以打破这个),但应该有一个很好的理由这样做。不过,这更像是承诺而非保证。
第二个概念保证也是承诺而不是保证,即方法或财产将像其他情况一样工作。
人们习惯于让IList的索引器以相当快的速度运行 - O(1)或更糟糕的O(log n) - 并打破这个概念上的承诺会导致人们严重使用你的对象。
这里没有具体的规则。您当然可以将IList实现为链接列表,并且遭受O(n)索引获取。您还可以实现链接列表,使其不保留其计数记录(由框架提供的记录)并具有O(n)Count属性。但是人们更有可能使用它。
组件设计的一部分不仅仅是确保工作正常并且运行良好,而是指导它们的使用。实现IList的链表在后一点会失败,因此可以提出一个强有力的论据,即它不会像提供的那样好。
答案 3 :(得分:2)
LinkedList实际上是一种广为人知的列表数据结构,具有以下操作复杂性:
Insertion: O(N)
Removal: O(1)
Indexing: O(N)
而List是一个连续数组,具有以下算法复杂性:
Insertion*: O(1)
Removal*: O(N)
Indexing: O(1)
它们不提供通用接口,因为它会误导接口的用户并使程序效率变得不可预测。 有关更多信息,请查阅有关算法和数据结构的书籍。
答案 4 :(得分:1)
LinkedList不是List。列表是对象的单个维度集合。 LinkedList是一个节点集合,与Dictionary更紧密地对齐。它的需求与常规List不相似,但更专门用于允许节点遍历和组织行为。
答案 5 :(得分:0)
“列表”是数据结构术语不是链表;它实际上是一个数组 - 使用索引器可以直接访问列表项,索引器在链表中不可用(不实用)。
答案 6 :(得分:0)
历史怪癖:在.NET 1.1中,ArrayList是一个类似于动态长度数组的类。
在.NET 2+中,List内部组织为一个数组。这意味着IList确实需要数组语义。
在.NET中,列表类似于数组,而不是列表.... (boing)
真正的链接列表具有恒定的时间插入,删除,但缓慢的枚举和较慢的随机访问。
数组有快速枚举和随机访问,但是插入/删除代价很高(O(n)和重新分配可能会导致完全不同的行为)
答案 7 :(得分:0)
这让我感到惊讶。传统上,列表只是你可以依赖元素顺序的东西,链表遵循这个,它应该实现IList而不是ICollection(集合不说出有关其元素顺序的任何内容。)
由于某些操作的复杂程度低于某些人的预期,因此我没有实施IList。我认为这是错误的。
答案 8 :(得分:-1)
因为按索引访问链接列表不是O(1)。
答案 9 :(得分:-1)
链接列表不是旨在通过索引访问的数据结构,但IList<T>
提供了索引访问功能。
因此,由于您无法通过索引访问链接列表中的项目,因此无法提供尝试执行此操作的方法。