您的位置:首页 > 编程语言 > C#

【c#迭代器】

2017-09-18 00:00 423 查看
在.NET中,迭代器模式被IEnumerator和IEnumerable及其对应的泛型接口所封装。如果一个类实现了IEnumerable接口,那么就能够被迭代;调用GetEnumerator方法将返回IEnumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,他是数据序列中的一个位置记录。迭代器只能向前移动,同一数据序列中可以有多个迭代器同时对数据进行操作。

以一个手动迭代器为例子,进行详解迭代器:假如我们有一个集合添加“我,爱,的,是,c#”五个字母,那么输出时想从第三个开始输出,结果既是“是,c#,我,爱,的”,该怎么实现?迭代器就登场了......

/// <summary>
/// 主题:C#扫盲之迭代器
/// 时间:2013-1-4 20:33:50
/// 描述:利用迭代器输出字符串,从自己编写到优化
/// 作者:白宁超
/// </summary>
/// <param name="args"></param>

Sample类的迭代及创建如下:

/// <summary>
/// 主题:类的迭代输出初始化字符串
/// 时间:2013-1-4 20:40:15
/// 描述:通过创建Sample,实现字符串从第三个数打印出
/// 作者:白宁超
/// </summary>
class Sample:IEnumerable
{
public  Object[] values;               //定义对象作为集合参数
public  int starting;           //定义迭代起始点
public Sample(Object[] values, Int32 starting) //构造方法
{
this.values = values;
this.starting = starting;
}
// 摘要:返回一个循环访问集合的枚举器。
// 返回结果:可用于循环访问集合的 System.Collections.IEnumerator 对象。
public IEnumerator GetEnumerator()
{
return new IterationSample(this);
}
}


IterationSample迭代如下:为Sample类GetEnumerator方法提供返回值

/// <summary>
/// 主题:构造类的返回值
/// 时间:2013-1-4 20:41:49
/// 描述: IterationSample类来实现迭代器本身,通过GetEnumerator方法返回集合值
/// 作者:白宁超
/// </summary>
class IterationSample : IEnumerator
{
Sample parent;//迭代的对象
int position;//当前游标的位置
internal IterationSample(Sample parent)
{
this.parent = parent;
position = -1;// 数组元素下标从0开始,初始时默认当前游标设置为 -1,即在第一个元素之前,
}
//获取集合中的当前元素
public object Current
{
get
{
if (position == -1 || position == parent.values.Length)//第一个之前和最后一个自后的访问非法
{
throw new InvalidOperationException();
}
int index = position + parent.starting;//考虑自定义开始位置的情况
index = index % parent.values.Length;
return parent.values[index];
}
}
//将枚举数推进到集合的下一个元素
public bool MoveNext()
{
if (position != parent.values.Length) //判断当前位置是否为最后一个,如果不是游标自增
{
position++;
}
return position < parent.values.Length;
}
//将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
public void Reset()
{
position = -1;//将游标重置为-1
}
}


/// <summary>
/// 主题:C#扫盲之迭代器
/// 时间:2013-1-4 20:33:50
/// 描述:利用迭代器输出字符串,从自己编写到优化
/// 作者:白宁超
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//简单迭代器操作
object[] values = { "我", "爱", "的", "是", "C#" };//初始化数组“我爱的是C#”
Sample collection = new Sample(values, 3);         //Sample类实例化
foreach (object x in collection)                    //循环打印
{
Console.WriteLine(x);
}
Console.ReadKey();
}


以上是手写迭代器,还有一个更简便的方法,可以省去IterationSample类的迭代,即只需要Sample类GetEnumerator方法添加for循环语句,利用yield ruturn便可得到我们所希望的结果:

// 摘要:返回一个循环访问集合的枚举器。
// 返回结果:可用于循环访问集合的 System.Collections.IEnumerator 对象。
public IEnumerator GetEnumerator()
{
//return new IterationSample(this);
//此方法减少代码量,是代码更优雅
for (int index = 0; index < this.values.Length; index++)
{
yield return values[(index + starting) % values.Length];
}
}


IEnumerable<T>在LINQ中最重要的一个接口,如果想要在LINQ To Object上实现自己的LINQ操作,就会觉得迭代的方便性。值得注意的是,yield return语句停止了方法的执行,而不是退出方法,要想退出需要yield break,这根普通方法中的return一样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: