C#枚举器和迭代器
【摘要】 C#枚举器和迭代器
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);
}
}
示例
- 定义一个可枚举类
class Colors : IEnumerable
{
string[] colors = { "blue", "red", "yellow" };
public IEnumerator GetEnumerator()
{
return new ColorEnumerator(colors);
}
}
- 定义可枚举类中使用到的枚举器
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;
}
}
- 使用可枚举类
static void Main(string[] args)
{
Colors colors = new Colors();
foreach (var item in colors)
{
Console.WriteLine(item);
}
Console.Read();
}
泛型枚举器
IEnumerator<T>
泛型枚举器与普通枚举器类似,不同之处在于普通枚举器的Current
属性是Object类型,在取出是需要进行转化(看上面while代码块中的代码),而泛型可以直接返回指定的类型。
迭代器
迭代器使用
迭代器简化了可枚举器和可枚举类型的编码工作。yield return
表示依次返回枚举中的下一项。
如何要实现上面的实例,只需要实现可枚举类:
class Colors
{
string[] colors = { "blue", "red", "yellow" };
public IEnumerator GetEnumerator()
{
return GetColorsEnumerator();
}
//返回枚举器
public IEnumerator<string> GetColorsEnumerator()
{
yield return "blue";
yield return "red";
yield return "yellow";
}
}
结果与上面示例完全相同
常见迭代器模式
- 迭代器返回枚举器
class Colors
{
public IEnumerator GetEnumerator()
{
return GetColors();
}
//该出返回的是枚举器
public IEnumerator<string> GetColors()
{
yield return ..;
yield return ..;
...
}
}
Colors colors = new Colors();
foreach (var item in colors)
{
Console.WriteLine(item);
}
- 迭代器返回可枚举类型
class Colors
{
//可以选择不实现该方法,让Colors类变成不可枚举类
public IEnumerator GetEnumerator()
{
return GetColors().GetEnumerator();
}
//该出返回的是可枚举类型
public IEnumerable<string> 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<string> A()
{
for (int i = 0; i < colors.Length; i++)
{
yield return colors[i];
}
}
public IEnumerable<string> 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();
}
迭代器作为属性
上面的迭代器是作为方法,可以将方法封装为属性,方便调用
class Colors
{
string[] colors = { "blue", "red", "yellow" };
public IEnumerable<string> A
{
get
{
for (int i = 0; i < colors.Length; i++)
{
yield return colors[i];
}
}
}
public IEnumerable<string> B
{
get
{
for (int i = colors.Length - 1; i >= 0; i--)
{
yield return colors[i];
}
}
}
}
使用方式基本相同,只不过是将方法调用改成了属性
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)