返回

C#枚举器和迭代器

发布时间:2023-02-12 11:39:08 208

C#枚举器和迭代器

使用foreach语句时,可以依次取出数组里面的元素,原因就是数组提供了“枚举器(Enumerator)”,枚举器知道元素的位置并返回请求项。

枚举器IEnumerator

枚举器实现了​​IEnumerator​​接口,该接口中有Current属性、MoveNext和Reset方法,foreach实现原理类似如下代码:

static void Main(string[] args)
{
int[] MyArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//可枚举类实现了GetEnumerator方法,获取枚举器
IEnumerator ie = MyArray.GetEnumerator();
while ( ie.MoveNext())
{
int i = (int)ie.Current;
Console.WriteLine(i);
}
}

示例

  1. 定义一个可枚举类
class Colors : IEnumerable
{
string[] colors = { "blue", "red", "yellow" };

public IEnumerator GetEnumerator()
{
return new ColorEnumerator(colors);
}
}
  1. 定义可枚举类中使用到的枚举器
class ColorEnumerator : IEnumerator
{
string[] colors;
int positon = -1;
public ColorEnumerator(string[] colors)
{
this.colors = colors;
for (int i = 0; i < colors.Length; i++)
{
this.colors[i] = colors[i];
}
}

public object Current
{
get
{
if (positon == -1 || positon >= colors.Length) throw new InvalidOperationException();
return colors[positon];
}
}

public bool MoveNext()
{
if(positon <colors.Length-1)
{
positon++;
return true;
}
else
{
return false;
}
}

public void Reset()
{
positon = -1;
}
}
  1. 使用可枚举类
static void Main(string[] args)
{
Colors colors = new Colors();
foreach (var item in colors)
{
Console.WriteLine(item);
}
Console.Read();
}

C#枚举器和迭代器_迭代器

泛型枚举器

​IEnumerator​

泛型枚举器与普通枚举器类似,不同之处在于普通枚举器的​​Current​​属性是Object类型,在取出是需要进行转化(看上面while代码块中的代码),而泛型可以直接返回指定的类型。

迭代器

迭代器使用

迭代器简化了可枚举器和可枚举类型的编码工作。​​yield return​​ 表示依次返回枚举中的下一项。

如何要实现上面的实例,只需要实现可枚举类:

class Colors 
{
string[] colors = { "blue", "red", "yellow" };

public IEnumerator GetEnumerator()
{
return GetColorsEnumerator();
}
//返回枚举器
public IEnumerator GetColorsEnumerator()
{
yield return "blue";
yield return "red";
yield return "yellow";
}
}

结果与上面示例完全相同

常见迭代器模式

  1. 迭代器返回枚举器
class Colors
{
public IEnumerator GetEnumerator()
{
return GetColors();
}
//该出返回的是枚举器
public IEnumerator GetColors()
{
yield return ..;
yield return ..;
...
}
}
Colors colors = new Colors();
foreach (var item in colors)
{
Console.WriteLine(item);
}
  1. 迭代器返回可枚举类型
class Colors
{
//可以选择不实现该方法,让Colors类变成不可枚举类
public IEnumerator GetEnumerator()
{
return GetColors().GetEnumerator();
}
//该出返回的是可枚举类型
public IEnumerable GetColors()
{
yield return ..;
yield return ..;
...
}
}
Colors colors = new Colors();
//如果实现GetEnumerator()方法,则使用以下方法
foreach (var item in colors)
{
Console.WriteLine(item);
}
//如果没有实现GetEnumerator()方法,则使用以下方法
foreach (var item in colors.GetColors())
{
Console.WriteLine(item);
}

多个迭代器

上面讲的迭代器有两种模式,为什么需要第2种方式?答案时候第2中方式更加灵活,比如可以实现多个迭代器

class Colors 
{
string[] colors = { "blue", "red", "yellow" };


public IEnumerable A()
{
for (int i = 0; i < colors.Length; i++)
{
yield return colors[i];
}
}

public IEnumerable B()
{
for (int i = colors.Length-1; i >=0; i--)
{
yield return colors[i];
}
}
}

使用

static void Main(string[] args)
{
Colors colors = new Colors();
foreach (var item in colors.A())
{
Console.WriteLine(item);
}
Console.WriteLine("--------------");
foreach (var item in colors.B())
{
Console.WriteLine(item);
}
Console.Read();
}

C#枚举器和迭代器_开发语言_02

迭代器作为属性

上面的迭代器是作为方法,可以将方法封装为属性,方便调用

class Colors
{
string[] colors = { "blue", "red", "yellow" };


public IEnumerable A
{
get
{
for (int i = 0; i < colors.Length; i++)
{
yield return colors[i];
}
}
}

public IEnumerable B
{
get
{
for (int i = colors.Length - 1; i >= 0; i--)
{
yield return colors[i];
}
}
}
}

使用方式基本相同,只不过是将方法调用改成了属性

 

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线