我正在尝试理解序列和列表之间的区别。
在F#中,两者之间有明显的区别。但是在C#中,我看到程序员将IEnumerable集合称为序列。是什么让IEnumerable成为一个序列,它返回一个对象来遍历集合?
也许真正的区别纯粹出现在函数式语言中?
答案 0 :(得分:7)
不是真的 - 你倾向于随机访问列表,以及能够快速获得计数等。不可否认链接列表没有随机访问性质......但是他们没有实现{ {1}}。特定平台提供的设施与一般概念之间存在灰色区域。
序列(由IList<T>
表示)是只读的,仅向前的,一次一个项目,并且可能是无限的。当然,序列的任何一个实现也可以是一个列表(例如IEnumerable<T>
)但是当你将它作为一个序列处理时,你基本上可以迭代它(重复),那就是它
答案 1 :(得分:4)
我认为混淆可能源于像List<T>
这样的集合实现接口IEnumerable<T>
这一事实。如果您通常具有子类型关系(例如,具有两个子类型Shape
和Rectangle
的超类型Circle
),则可以将该关系解释为“is-a”层次结构。
这意味着可以说“Circle
是 Shape
”,同样,人们会说“List<T>
是 IEnumerable<T>
“,即”list 是序列“。这是有道理的,因为列表是序列的特殊类型。通常,序列也可以懒惰地生成并且是无限的(并且这些类型也不能是列表)。列表无法生成的(完全有效)序列的示例如下所示:
// C# version // F# version
IEnumerable<int> Numbers() { let rec loop n = seq {
int i = 0; yield n
while (true) yield return i++; yield! loop(n + 1) }
} let numbers = loop(0)
对于F#也是如此,因为F#list
类型也实现了IEnumerable<T>
,但是函数式编程并没有强调面向对象的观点(以及启用它的隐式转换) “是一种”解释在F#中使用频率较低。)
答案 2 :(得分:2)
序列内容是按需计算的,因此您可以实现无限序列,而不会影响您的记忆。 所以在C#中你可以编写一个序列,例如
IEnumerable<int> Null() {
yield return 0;
}
它将返回无限的零序列。 你可以写
int[] array = Null().Take(10).ToArray()
尽管序列是无限的,但它将占用10 * 4字节的内存。 如您所见,C#确实区分了序列和集合