无法将带有[]的索引应用于类型为'System.Collections.Generic.IEnumerable<>的表达式

时间:2010-08-31 19:58:40

标签: c# generics ienumerable

IEnumerable中是否允许索引编译是否有任何特定原因。

我找到了解决问题的方法,但很想知道它为什么不允许索引。

谢谢,

8 个答案:

答案 0 :(得分:64)

因为它不是。

索引由IList涵盖。 IEnumerable的意思是“我拥有IList的一些权力,但不是所有权力。”

某些集合(如链接列表)无法以实用方式编制索引。但是可以逐项访问它们。 IEnumerable适用于此类集合。请注意,集合可以实现IList和& IEnumerable(和许多其他人)。您通常只会将IEnumerable视为函数参数,这意味着该函数可以接受任何类型的集合,因为它只需要最简单的访问模式。

答案 1 :(得分:44)

IEnumerable<T>界面不包含indexer,您可能会将其与IList<T>混淆

如果对象确实是IList<T>(例如List<T>或数组T[]),请尝试对类型IList<T>进行引用。

否则,您可以使用myEnumerable.ElementAt(index)使用Enumerable.ElementAt扩展方法。这适用于所有IEnumerable<T>。 请注意,除非(运行时)对象实现IList<T>,否则将导致枚举所有第一个index + 1项,除最后一个之外的所有项都将被丢弃。

编辑: 作为解释,IEnumerable<T>只是一个表示“暴露枚举器的那个”的接口。具体实现可能是某种内存列表, 允许通过索引快速访问,或者它可能不是。例如,它可能是一个无法有效满足这种查询的集合,例如链表(如James Curran所述)。它甚至可能是内存数据结构的 no sort ,例如迭代器,其中项目是按需生成('生成'),或者是从某些内容获取项目的枚举器远程数据源。由于IEnumerable<T>必须支持所有这些情况,因此索引器将从其定义中排除。

答案 2 :(得分:3)

一个原因可能是IEnumerable可能包含未知数量的项目。一些实现在迭代时生成项列表(有关样本,请参阅yield)。使用索引访问项目时效果不佳。这需要你知道列表中至少有那么多项目。

答案 3 :(得分:3)

如果您的可枚举类型是下面的字符串

,则可以使用索引编制
((string[])MyEnumerableStringList)[0]

答案 4 :(得分:2)

[] -operator已解析为访问属性this[sometype index],其实现取决于Element- Collection

Enumerable-Interface首先声明了一个Collection 的蓝图

以此示例来说明清洁界面分离的有用性:

var ienu = "13;37".Split(';').Select(int.Parse);
//provides an WhereSelectArrayIterator
var inta = "13;37".Split(';').Select(int.Parse).ToArray()[0];
//>13
//inta.GetType(): System.Int32

另请查看[] -operator 的语法:

  //example
public class SomeCollection{
public SomeCollection(){}

 private bool[] bools;

  public bool this[int index] {
     get {
        if ( index < 0 || index >= bools.Length ){
           //... Out of range index Exception
        }
        return bools[index];
     }
     set {
        bools[index] = value;
     }
  }
//...
}

答案 5 :(得分:1)

接口的概念通常是公开一种基线契约,通过该契约可以保证对对象执行工作的代码具有该对象提供的某些功能。在IEnumerable<T>的情况下,该合同恰好是“您可以逐个访问我的所有元素。”

仅基于此合同可以编写的方法种类很多。有关的示例,请参阅Enumerable课程。

但要仅仅考虑一个具体问题:考虑Sum。为了总结一堆物品,你需要什么?你需要什么合同?答案很简单:只是一种方式来查看每个项目,而不是更多。无需随机访问。甚至不需要所有项目的总数。

IEnumerable<T>界面添加索引器会在两个方面造成不利影响:

  1. 需要上述合同的代码(访问一系列元素),如果需要IEnumerable<T>接口,则会受到人为限制,因为它无法处理任何未实现索引器的类型,甚至虽然处理这种类型应该完全符合代码的能力。
  2. 任何想要公开一系列元素但没有适当配备以通过索引提供随机访问的类型(例如LinkedList<T>Dictionary<TKey, TValue>)现在必须提供一些低效的< em>模拟索引,否则放弃IEnumerable<T>接口。
  3. 所有这些都说,考虑到接口的目的是在给定场景中提供最低要求功能的保证,我真的认为IList<T>接口很差设计的。或者更确切地说,在我看来,缺乏an interface "between" IEnumerable<T> and IList<T>(随机访问,但没有修改)是BCL的一个不幸的疏忽。

答案 6 :(得分:0)

您可以使用 ToList 转换为列表。例如,

SomeItems.ToList()[1]

答案 7 :(得分:0)

我有一个不允许空值的列,我插入了一个空值。