C#中的迭代器模式
- 迭代器模式提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示
- 代码演示
/// <summary>
/// 聚合接口
/// </summary>
public interface IListCollection
{
Iterator GetIterator();
}
/// <summary>
/// 迭代器接口
/// </summary>
public interface Iterator
{
int GetCurrent();
bool MoveNext();
void Reset();
}
/// <summary>
/// 具体聚合类
/// </summary>
public class Persons : IListCollection
{
private List<int> _persons;
public Persons()
{
_persons = new List<int>();
}
public void Add(int value)
{
_persons.Add(value);
}
public Iterator GetIterator()
{
return new PersonIterator(this._persons);
}
}
/// <summary>
/// 具体迭代器类
/// </summary>
public class PersonIterator : Iterator
{
private List<int> _array;
private int index;
internal PersonIterator(List<int> array)
{
_array = array;
index = -1;
}
int Iterator.GetCurrent()
{
return _array[index];
}
bool Iterator.MoveNext()
{
if (index >= _array.Count - 1)
{
return false;
}
index++;
return true;
}
void Iterator.Reset()
{
index = -1;
}
}
实现迭代器模式有以下几个要点:
1.聚合接口和迭代器接口。
2.具体聚合类,定义数据的存储容器,添加元素的方法等,还有获取具体迭代器的方法。
3.具体迭代器类,定义迭代内部实现的一些具体细节等。
客户端调用:
static void Main(string[] args)
{
Persons persons = new Persons();
for (int i = 0; i < 5; i++)
{
persons.Add(i);
}
Iterator temp = persons.GetIterator();
while (temp.MoveNext())
{
Console.WriteLine(temp.GetCurrent());
}
Console.Read();
}
结果:
- C#中的迭代器模式
在C#中,很多的容器类都实现了迭代器模式,比如栈、队列、List、字典等,都能够使用Foreach直接进行迭代。
//
// 摘要:
// 公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。
public interface IEnumerable
{
//
// 摘要:
// 返回一个循环访问集合的枚举器。
//
// 返回结果:
// 可用于循环访问集合的 System.Collections.IEnumerator 对象。
IEnumerator GetEnumerator();
}
//
// 摘要:
// 支持对非泛型集合的简单迭代。
public interface IEnumerator
{
//
// 摘要:
// 获取集合中的当前元素。
//
// 返回结果:
// 集合中的当前元素。
object Current { get; }
//
// 摘要:
// 将枚举数推进到集合的下一个元素。
//
// 返回结果:
// 如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。
//
// 异常:
// T:System.InvalidOperationException:
// 在创建了枚举数后集合被修改了。
bool MoveNext();
//
// 摘要:
// 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
//
// 异常:
// T:System.InvalidOperationException:
// 在创建了枚举数后集合被修改了。
void Reset();
}
这是C#中标准的迭代器模式相关的接口,C#中可迭代的容器都实现了该接口,并且可以直接通过Foreach进行迭代输出。
下面,展示一个比较简单的栈的部分源代码
class Stack : IEnumerable//具体的聚合类,实现IEnumerable接口
{
private object[] _array;
private int _size;
private int _version;
private const int _defaultCapacity = 10;
public Stack()
{
_array = new object[10];
_size = 0;
_version = 0;
}
public virtual IEnumerator GetEnumerator()//实现IEnumerable的接口
{
return new StackEnumerator(this);
}
public virtual object Peek()
{
if (_size == 0)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack"));
}
return _array[_size - 1];
}
public virtual object Pop()
{
if (_size == 0)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack"));
}
_version++;
object result = _array[--_size];
_array[_size] = null;
return result;
}
public virtual void Push(object obj)
{
if (_size == _array.Length)
{
object[] array = new object[2 * _array.Length];
Array.Copy(_array, 0, array, 0, _size);
_array = array;
}
_array[_size++] = obj;
_version++;
}
[Serializable]
private class StackEnumerator : IEnumerator//具体的迭代器类,实现迭代器接口
{
private Stack _stack;
private int _index;
private int _version;
private object currentElement;
public virtual object Current
{
get
{
if (_index == -2)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
}
if (_index == -1)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded"));
}
return currentElement;
}
}
internal StackEnumerator(Stack stack)
{
_stack = stack;
_version = _stack._version;
_index = -2;
currentElement = null;
}
public virtual bool MoveNext()
{
if (_version != _stack._version)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
}
bool flag;
if (_index == -2)
{
_index = _stack._size - 1;
flag = (_index >= 0);
if (flag)
{
currentElement = _stack._array[_index];
}
return flag;
}
if (_index == -1)
{
return false;
}
flag = (--_index >= 0);
if (flag)
{
currentElement = _stack._array[_index];
}
else
{
currentElement = null;
}
return flag;
}
public virtual void Reset()
{
if (_version != _stack._version)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
}
_index = -2;
currentElement = null;
}
}
在Stack的源代码中,Stack实现了IEnumerable接口的GetEnumerator()方法,用于返回一个IEnumerator类型的迭代器。而在Stack中声明了一个StackEnumerator 的具体迭代器类,实现IEnumerator接口,并且针对Stack的数据结构,实现了IEnumerator接口的各种方法。