这让我觉得奇怪的是,从IEnumerable<T>
继承任何类并不需要实现Add(T object)
,即使如果你想初始化类实例时使用collection initializers,你必须实现Add(T object)
。添加(T对象)不是IEnumerable的合同方法<T> - 为什么?
为什么这样呢?
这让我觉得奇怪的是,从IEnumerable<T>
继承任何类并不需要实现Add(T object)
,即使如果你想初始化类实例时使用collection initializers,你必须实现Add(T object)
。添加(T对象)不是IEnumerable的合同方法<T> - 为什么?
为什么这样呢?
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
。
IEnumerable是“堆栈”的底层,它具有枚举整个列表所需的基础知识,这使它成为只读函数。
我想最大的原因是并非所有的集合都必须是Enumerable。此外,事实上你可以有其他可枚举的项目,比如计算或其他过程。
例如,您可以使用带有Yield命令的IEnumerable来计算出素数或Fibonacci序列。这真的取决于你。
至于集合初始值设定项,因为您正在处理集合,我假设初始值设定项可能使用类似于Yield命令的项目,所以它使用IEnumerable将您初始化的值生成为Add方法。
我的两分钱。
更令人信服的原因是并非所有的枚举都需要是集合。 – erikkallen 2009-12-18 11:51:38
正如其他人所说,IEnumerable
是一个只读接口,指示一个序列可以迭代,仅此而已。
什么是集合:
你宽约为什么收集initialisers需要
IEnumerable
组合和Add
方法可能best addressed by Mads Torgersen问题?然后我们发现了什么?我们的 自己的(公共)班级(与公众 构造函数)中只有14个实施
ICollection<T>
!很明显,在框架中有 很多收藏, 所以很明显,我们需要一些 其他方式来告诉 是否是一个集合类。 LINQ到 救援一次:随着修改 版本的查询很容易 建立我们的公共 类与公共构造有 之间的有:
189具有公共
Add
方法实施System.Collections.IEnumerable
42具有公共
Add
方法,但没有实现System.Collections.IEnumerable
如果你看一下由 这两个查询返回的类,你就会意识到, 主要有两种 的 根本不同含义的名字“添加”:
a)将参数变成 集合,或
b)返回参数和接收方的算术和 。
的人实际上是在 (直接或间接)写的集合类时实施 非泛型
IEnumerable
接口 非常好,所以 这原来是一个Add
方法是否是 一个相当可靠的 指标第一或第二种。因此,对于 我们的目的操作答案 标题问题就变成了:集合是实现
IEnumerable
并具有公共Add
方法
直接从马的嘴这里输入:http ://blogs.msdn.com/madst/archive/2006/10/10/What-is-a-collection_3F00_.aspx – LukeH 2009-12-18 11:48:55
值得注意的是'foreach'确实在'IEnumerable'上使用鸭子打字,所以有可能迭代使用'foreach'而不能使用集合初始值设定项。 – thecoop 2009-12-18 11:50:11