C# IEnumerable和IEnumerator接口浅析

温故而知新,可以为师矣,有空经常复习一下基础知识是有必要的,并且能加深理解和记忆。

Foreach常用于循环访问集合,对实现IEnumerable的接口的容器进行遍历,IEnumerable和IEnumerator接口我有时候也有点迷糊,按官方的解释,IEnumerable是枚举器接口,IEnumerator是迭代器接口,从字面意思来看相差不大,逐一分析一下。

IEnumerable接口

public interface IEnumerable

{

IEnumerator GetEnumerator();

}

继承IEnumerable接口的类需实现暴露出来的GetEnumerator()方法,并返回一个IEnumerator接口对象,看来真正做事的是IEnumerator,F12看一下IEnumerator又有什么鬼东西。

IEnumerator接口

public interface IEnumerator

{

object Current { get; }

bool MoveNext();

void Reset();

}

IEnumerator接口有三个东东,一个属性Current,返回当前集合中的元素,方法MoveNext()移动到下一个,遍历不都是向后遍历的嘛,Reset(),字面意思重置,这个容易理解。做个假设:既然IEnumerable接口返回是IEnumerator接口迭代器来实现的,那么仅继承IEnumerator迭代器接口能不能实现一个自定义容器?

定义一个Phone类

public class Phone

{

public string Name;

public Phone(string name)

{

this.Name = name;

}

}

定义一个名为MyEnumerator迭代器,并现实它接口IEnumerator

public class MyEnumerator : IEnumerator

{

Phone[] p;

int idx = -1;

public MyEnumerator(Phone[] t)

{

p = t;

}

public object Current

{

get

{

if (idx == -1)

return new IndexOutOfRangeException();

return p[idx];

}

}

public bool MoveNext()

{

idx++;

return p.Length > idx;

}

public void Reset()

{

idx = -1;

}

}

class Program

{

static void Main(string[] args)

{

      show("-----------IEnumerator------------");

Phone[] phones = new Phone[] { new Phone("iPhone 7s"), new Phone("iPhone 6s"), new Phone("iPhone 5s") };

MyEnumerator enumerator = new MyEnumerator(phones);

while (enumerator.MoveNext())

{

Phone p = enumerator.Current as Phone;

show(p.Name);

}

Console.ReadKey();

}

static void show(string i)

{

Console.WriteLine(i);

}

}

结果显示:

果然不出所料,真正做事情的是IEnumerator接口,即可循环访问自定义的一个容器,不过,初衷是想用Foreach来做循环访问、遍历的。那好,那就只能显示IEnumerable接口来做。稍稍改造一下Phone类:

public class Phone : IEnumerable

{

public string Name ;

public Phone(string name)

{

this.Name = name;

}

Phone[] p;

public Phone(Phone[] t)

{

p = t;

}

public IEnumerator GetEnumerator()

{

return new MyEnumerator(p);

}

}

static void Main(string[] args)

{

show("-----------IEnumerator------------");

Phone[] phones = new Phone[] { new Phone("iPhone 7s"), new Phone("iPhone 6s"), new Phone("iPhone 5s") };

MyEnumerator enumerator = new MyEnumerator(phones);

while (enumerator.MoveNext())

{

Phone p = enumerator.Current as Phone;

show(p.Name);

}

show("-----------IEnumerable------------");

Phone phoneList = new Phone(phones);

foreach (Phone p in phoneList)

{

show(p.Name);

}

Console.ReadKey();

}

结果显示:

大功告成,再扩展成通用的容器PhonePackage,继承泛型IEnumerable<T>接口即可。

public class PhonePackage<T> : IEnumerable<T>

{

private List<T> dataList = null;

public void Add(T t)

{

if (dataList == null)

dataList = new List<T>();

dataList.Add(t);

}

public IEnumerator<T> GetEnumerator()

{

foreach (T t in dataList)

{

yield return t;

}

}

IEnumerator IEnumerable.GetEnumerator()

{

foreach (T t in dataList)

{

yield return t;

}

}

}

static void Main(string[] args)

{

show("-----------IEnumerator------------");

Phone[] phones = new Phone[] { new Phone("iPhone 7s"), new Phone("iPhone 6s"), new Phone("iPhone 5s") };

MyEnumerator enumerator = new MyEnumerator(phones);

while (enumerator.MoveNext())

{

Phone p = enumerator.Current as Phone;

show(p.Name);

}

show("-----------IEnumerable------------");

Phone phoneList = new Phone(phones);

foreach (Phone p in phoneList)

{

show(p.Name);

}

show("-----------IEnumerable<T>------------");

PhonePackage<Phone> phonePackage = new PhonePackage<Phone>();

phonePackage.Add(new Phone("iPhone 7s"));

phonePackage.Add(new Phone("iPhone 6s"));

phonePackage.Add(new Phone("iPhone 5s"));

foreach (Phone p in phonePackage)

{

show(p.Name);

}

Console.ReadKey();

}

static void show(string i)

{

Console.WriteLine(i);

}

结果显示:

IEnumerator迭代器接口挺啰嗦的,yield是简化了遍历的语法糖而已。

以上是 C# IEnumerable和IEnumerator接口浅析 的全部内容, 来源链接: utcz.com/z/319926.html

回到顶部