添加(T对象)不是IEnumerable的合同方法<t> - 为什么?</t>

时间:2009-12-18 11:34:17

标签: c# ienumerable

令我感到奇怪的是,任何继承自IEnumerable<T>的类都不需要实现Add(T object),即使你想在初始化类实例时使用collection initializers,必须实施Add(T object)

为什么会这样?

5 个答案:

答案 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是一个只读接口,表明序列可以迭代,仅此而已。

关于为什么集合初始化者需要结合IEnumerableAdd方法的更广泛的问题可能是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)

因为IEnumerable<T>枚举集合的界面,所以没有别的。

来自MSDN

  

公开支持的枚举器   对集合的简单迭代   指定类型。

答案 3 :(得分:0)

当涉及到“列表”时,IEnumerable是最底层的,它具有枚举列表所需的基础知识,这使得它只读函数。

答案 4 :(得分:0)

我猜最大的原因是并非所有收藏品都必须是可枚举的。此外,您可以拥有可枚举的其他项目,例如计算或其他过程。

例如,您可以将IEnumerable与Yield命令一起使用来计算素数或斐波纳契数列。这完全取决于你。

至于集合初始值设定项,因为你正在处理一个集合,我假设初始化器可能正在使用类似于Yield命令的东西,所以它使用IEnumerable将你的初始值输出到Add方法。

我的两分钱。