为什么IEnumerable<T>没有实现Add(T)方法?

14

刚才偶然发现,Add(T)定义在ICollection<T>中,而不是IEnumerable<T>。而且Enumerable.cs中的扩展方法不包含Add(T),我觉得这真的很奇怪。因为一个对象是可枚举的,它必须“看起来”像是一组项目的集合。有人能告诉我为什么吗?


如果 IEnumerable<T> 要求实现 Add,那么会有更多反向的问题:为什么 IEnumerable<T>Add。现在的做法非常有用 :) - nawfal
6个回答

49

IEnumerable<T>是元素的序列,可以将其视为仅向前的光标。由于许多这些序列正在生成值、数据流或来自数据库的记录集,因此向它们Add添加项毫无意义。


9
+1 使用“序列”这个词,因为IEnumerable确切地代表了一个序列,而不是一种集合。 - OregonGhost

13

IEnumerable 用于读取,而不是写入。


11
一个“可枚举”就是可以枚举并发现所有项的东西。这并不意味着你可以添加它们。
能够枚举是许多类型对象都具有的特征。例如,它被数组和集合所共享。但是你不能在不改变数组结构的情况下向其添加内容,而集合则专门用于添加和移除项目。
从技术上讲,你可以使用Concat<>将另一个可枚举对象 “添加” 到一个可枚举对象中,但是这只是创建一个枚举器,从一个枚举到另一个枚举对象,从而产生单个连续集合的假象。

3
每个 `ICollection` 应该是一个 `IEnumerable`(我认为,而且 .NET Framework 团队似乎也同意我的看法 ;-)),但反过来并不总是有意义的。在这个世界上,存在着一种“类集合对象”的层次结构,你假设可枚举对象是可以添加项的集合并不符合这种层次结构。
例如:一个包含主要颜色名称的列表将是一个返回 `"Red"`、`"Blue"` 和 `"Green"` 的 `IEnumerable`。在像这样填充的“集合”上执行 `primaryColors.Add("Bright Purple")` 操作根本没有逻辑意义。
...whatever...
{
    ...
    var primaryColors = EnumeratePrimaryColors();
    ...
}

private static IEnumerable<string> EnumeratePrimaryColors() {
    yield return "Red";
    yield return "Blue";
    yield return "Green";
}

ICollection 继承自 IEnumerable,而 ICollection<T> 继承自 IEnumerable<T>(后者又继承自 IEnumerable)。换句话说,你是正确的:每个 ICollection 都是一个 IEnumerable - Steven

2
正如其名称所示,您可以枚举(循环)IEnumerable,这就是它的全部。 当您想要添加内容时,它不再仅仅是可枚举的,因为它具有额外的功能。
例如,数组是IEnumerable,但数组具有固定长度,因此无法向其中添加新项。
IEnumerable只是所有类型集合(甚至是只读集合-显然没有Add()方法)的“基础”。 您添加到此“基本接口”的功能越多,它就越具体。

2
名称已经说明了一切。IEnumerable仅用于枚举项。ICollection是实际的项集合,因此支持Add方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接