IEnumerable和IEnumerator的使用
我对这两个接口的看法:
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/// <summary>
/// 这个是一个人的类,有姓和名两个字段
/// </summary>
public class Person
{
public Person(string fName, string lName)
{
this.firstName = fName;
this.lastName = lName;
}
public string firstName;
public string lastName;
}
/// <summary>
/// 这个是个集合类,实现了IEnumerable,
/// 表明People可以被foreach遍历
/// </summary>
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];
}
}
/// <summary>
/// 接口的实现,返回的是一个PeopleEnum的一个类对象
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator()
{
return new PeopleEnum(_people);
}
}
/// <summary>
/// 专门实现遍历的类,必须实现IEnumerator接口
/// 这样才能正常的进行数据遍历
/// </summary>
public class PeopleEnum : IEnumerator
{
public Person[] _people;
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;
public PeopleEnum(Person[] list)
{
_people = list;
}
public bool MoveNext()
{
position++;
return (position < _people.Length);
}
public void Reset()
{
position = -1;
}
public object Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
class App
{
static void Main()
{
Person[] peopleArray = new Person[3]
{
new Person("John", "Smith"),
new Person("Jim", "Johnson"),
new Person("Sue", "Rabon"),
};
People peopleList = new People(peopleArray);
foreach (Person p in peopleList)
Console.WriteLine(p.firstName + " " + p.lastName);
}
}
- 如果要实现foreach的调用,就必须实现这两个接口。
- IEnumerable接口:实现了这个接口的类可以使用foreach,实现的方法要返回的是一个对象(该对象是要遍历的对象,可以返回自身,也可以返回新的对象)。
- IEnumerator接口实现的方法是如何操作IEnumerable返回的对象(即:IEnumerable返回的对象必须实现IEnumerator这个接口)
- 两个接口,离开了任何一个,都不能单独运行
- 为什么这一套东西要分开?根据2和3,可以为一个类专门写一个foreach的类,这样使原类更简洁。
我复制粘贴了MSDN的例子:
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/// <summary>
/// 这个是一个人的类,有姓和名两个字段
/// </summary>
public class Person
{
public Person(string fName, string lName)
{
this.firstName = fName;
this.lastName = lName;
}
public string firstName;
public string lastName;
}
/// <summary>
/// 这个是个集合类,实现了IEnumerable,
/// 表明People可以被foreach遍历
/// </summary>
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];
}
}
/// <summary>
/// 接口的实现,返回的是一个PeopleEnum的一个类对象
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator()
{
return new PeopleEnum(_people);
}
}
/// <summary>
/// 专门实现遍历的类,必须实现IEnumerator接口
/// 这样才能正常的进行数据遍历
/// </summary>
public class PeopleEnum : IEnumerator
{
public Person[] _people;
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;
public PeopleEnum(Person[] list)
{
_people = list;
}
public bool MoveNext()
{
position++;
return (position < _people.Length);
}
public void Reset()
{
position = -1;
}
public object Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
class App
{
static void Main()
{
Person[] peopleArray = new Person[3]
{
new Person("John", "Smith"),
new Person("Jim", "Johnson"),
new Person("Sue", "Rabon"),
};
People peopleList = new People(peopleArray);
foreach (Person p in peopleList)
Console.WriteLine(p.firstName + " " + p.lastName);
}
}
网络上也有一些这类型的例子,但是写的根本就是错误的,让我看了好久都没明白怎么回事。
这个例子运行时看似是正确的,但是如果把那个对象foreach两次就会出错。因为在foreach第二次的时候,index已经到了最大值。
所以,大家可以参考MSDN的例子,运行都是正常,并且代码看起来更优雅。