为什么使用数组而不是链接列表实现IEnumerable(或IList)?

时间:2015-02-22 07:02:27

标签: c# arrays data-structures ienumerable

我正在阅读有关实现IENumerable接口方法的基本教程,并发现所有示例都使用数组。我的印象是IENumerable与链表非常相似。我相信数组和链表是两个完全不同的数据结构。

那么为什么当我们实际认为它们完全不同时,使用另一个(数组)实现一个(链表)?

这是MSDN页面上代码的样子:

// Collection of Person objects. This class 
// implements IEnumerable so that it can be used 
// with ForEach syntax. 
public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }

// Implementation for the GetEnumerator method.
    IEnumerator IEnumerable.GetEnumerator()
    {
       return (IEnumerator) GetEnumerator();
    }

    public PeopleEnum GetEnumerator()
    {
        return new PeopleEnum(_people);
    }
}

我错过了IENumerable的实现吗?

编辑:我现在明白,IENumerable并不一定像链表。但是,MSDN中的此代码使用数组实现IList:

class SimpleList : IList
{
    private object[] _contents = new object[8];
    private int _count;

    public SimpleList()
    {
        _count = 0;
    }

    // IList Members 
    public int Add(object value)
    {
        if (_count < _contents.Length)
        {
            _contents[_count] = value;
            _count++;

            return (_count - 1);
        }
        else
        {
            return -1;
        }
    }
//etc...
}

3 个答案:

答案 0 :(得分:4)

  

我的印象是IENumerable本质上非常   类似于链表。

我不确定你的印象在哪里。实现IEnumerableIEnumerable<T>的对象意味着“此对象公开了一个枚举器,使其可迭代”,它与链表的实现没有任何关系,或者数组。他们都具有可迭代的共同特征。这是对来电者的约束性合同。

  

那么为什么一个(链表)使用另一个来实现呢?   (数组)当我们真的认为它们完全不同时?

链接列表可以将数组存储为实现细节,但这肯定是一个糟糕的设计选择。

您可能会注意到List<T>也使用数组作为内部存储,一旦达到内部数组的最大大小,它就会重新调整大小。

答案 1 :(得分:0)

IEnumerableIEnumerable<T>不是链接列表。它们是提供枚举访问的接口。

以这种方式思考:IEnumerable是一个在枚举时提供0-n值的承诺(例如,通过使用foreach)。

许多真正的课程都能实现这一承诺。列表,数组,各种集合,如果你为它们编程,你自己的类可以这样做。如何从容器中获取 的容器,IEnumerable只说明了如何从获取数据容器用它来做某事。

这是一个非常简单的解释,您可能希望稍后在阅读此概念时阅读延迟执行

答案 2 :(得分:0)

简短回答:IEnumerable与链接列表“相似”只是因为它定义了一系列值。但是,一系列值也可以用许多其他方式定义,包括作为数组。

IEnumerable类型是interface。它只规定必须公开展示的内容;它没有以任何特定的方式决定实现应该是什么。

IEnumerable的情况下,实现该接口必须做的唯一事情是实现名为GetEnumerator()的方法,该方法必须返回另一个接口IEnumerator的实例。该接口必须依次实现名为Current的属性,该属性返回object的实例,以及名为MoveNext()的方法,该方法通知IEnumerator对象选择下一个项目枚举。

(该接口还需要实现Reset()方法,但是该接口的许多实现只为此方法抛出NotSupportedException ... CurrentMoveNext()成员是最小化以实现接口的有用实现。)

枚举可以以适合实现它的对象的任何方式实现。 System.Linq.Enumerable类型甚至包括简单地重复相同值的实现,或者发出一系列整数的实现。该类型成员的本身存储枚举;他们要么从头开始创建一个,要么改造现有的一个。

同样,您可以枚举文件中的文本行,或随机选择数字,或者反转数组的元素。唯一重要的是你有一些机制来选择一系列的值。

您发布的示例实际上并未向我们显示IEnumerator的实现...有一些名为PeopleEnum的未知类处理枚举。据推测,这个类只是将一个索引存储到传递给它的对象的数组中,按顺序返回每个元素(它也可以使用"iterator method"实现,但它不需要一个完整的其他类型来完成,所以我猜它不是。)

我希望上述内容有助于解决问题。 :)