令我感到奇怪的是,任何继承自IEnumerable<T>
的类都不需要实现Add(T object)
,即使你想在初始化类实例时使用collection initializers,必须实施Add(T object)
。
为什么会这样?
答案 0 :(得分:6)
IEnumerable<T>
是一个只读界面 - 它只是代表“一个序列”。
集合初始化程序需要Add
才能工作,但是它们首先检查类型是否实现IEnumerable
以确保它确实是某些描述的集合类型。它们不需要通用形式,因为这对于某些2.0之前的代码(特别是各种UI集合不实现IEnumerable<T>
IIRC)具有限制性,并且它们不需要特定的 Add
签名作为集合初始值设定项可以与不同数量的参数一起使用。例如,Dictionary<TKey, TValue>
有Add(TKey value, TValue value)
,因此您可以使用:
var dictionary = new Dictionary<string, int>
{
{ "Jon", 33 },
{ "Tom", 6 }
};
这意味着它不能仅限于(例如)IList
,它只有单argumnet Add
方法。它在某种程度上需要鸭子打字,但IEnumerable
要求是为了确保Add
真正意味着“将一个项目添加到集合中”而不是完全不同的东西。编译器不使用它实现IEnumerable
的事实 - 例如,它在构建集合时从不调用GetEnumerator
。
答案 1 :(得分:2)
正如其他人所说,IEnumerable
是一个只读接口,表明序列可以迭代,仅此而已。
关于为什么集合初始化者需要结合IEnumerable
和Add
方法的更广泛的问题可能是best addressed by Mads Torgersen:
什么是收藏?
那时我们发现了什么?我们只有14个 自己的(公共)课程(公共) 构造者)实施
ICollection<T>
!显然有一个 框架中有更多的集合, 很明显我们需要一些 告诉其他事情的其他方式 是一个集合类。 LINQ来了 再次救援:经过修改 查询的版本很容易 在我们的公众中建立 那里有公共建设者的班级 是:
189公开
Add
方法和实施System.Collections.IEnumerable
42有公开
Add
方法但不实施System.Collections.IEnumerable
如果查看返回的类 这两个问题,你意识到了 基本上有两个 从根本上说是不同的含义 名称“添加”:
a)将参数插入a 收集,或
b)返回算术和 论证和接收者。
人们其实非常擅长 (直接或间接)实施 非泛型
IEnumerable
接口 在编写集合类时,如此 结果证明是非常可靠的 是Add
方法的指标 第一种或第二种。因此 我们的目的是操作的答案 标题问题变成:集合是一种实现的类型
IEnumerable
并公开Add
方法
答案 2 :(得分:0)
答案 3 :(得分:0)
当涉及到“列表”时,IEnumerable是最底层的,它具有枚举列表所需的基础知识,这使得它只读函数。
答案 4 :(得分:0)
我猜最大的原因是并非所有收藏品都必须是可枚举的。此外,您可以拥有可枚举的其他项目,例如计算或其他过程。
例如,您可以将IEnumerable与Yield命令一起使用来计算素数或斐波纳契数列。这完全取决于你。
至于集合初始值设定项,因为你正在处理一个集合,我假设初始化器可能正在使用类似于Yield命令的东西,所以它使用IEnumerable将你的初始值输出到Add方法。
我的两分钱。