.NET中的迭代器(Iterator)
更新记录
本文迁移自Panda666原博客,原发布时间:2021年6月30日。
一、迭代器介绍#
C#2.0开始,我们可以使用迭代器(iterator)。编译器自动把我们定义的迭代器生成 可枚举类型 或 枚举器。迭代器需要System.Collections.Generic命名空间,要使用using引用它。
using System.Collections.Generic;
二、声明迭代器#
迭代器看起来非常像一个方法,但实际上是有本质区别的。编译器将迭代器转换为私有类,然后在类中实现IEnumerable
System.Collection.IEnumerable
System.Collection.Generic.IEnumerable<T>
System.Collection.IEnumerator
System.Collection.Generic.IEnumerator<T>
在迭代器中通过yield return语句声明枚举中的下一项,枚举器不会一次返回所有元素,每次访问Current属性返回一个新值,iterator可以在method, property, indexer内实现。
实例:返回可枚举类型的迭代器
public class PandaTestClass
{
public IEnumerable<string> GetEnumerator()
{
yield return "Panda";
yield return "Cat";
yield return "Dog";
yield return "Monkey";
yield return "Donkey";
}
}
实例:返回枚举器的迭代器
public class PandaTestClass:IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
yield return "Panda";
yield return "Cat";
yield return "Dog";
yield return "Monkey";
yield return "Donkey";
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
实例:可正序取数也可反向取数的迭代器
public class PandaTestClass
{
private string[] animals { get; set; }
public PandaTestClass()
{
this.animals = new string[]
{
"Panda",
"Cat",
"Dog",
"Monkey",
"Donkey"
};
}
/// <summary>
/// 正序访问
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetAnimal()
{
foreach (var item in this.animals)
{
yield return item;
}
}
/// <summary>
/// 反序访问
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetAnimalReverse()
{
var animalsReversed = this.animals.Reverse();
foreach (var item in animalsReversed)
{
yield return item;
}
}
}
实例:在属性中定义迭代器
class PandaTestClass
{
public IEnumerable<int> SomeProp
{
get
{
yield return 666;
yield return 888;
yield return 999;
}
}
public IEnumerator<int> SomeProp2
{
get
{
yield return 666;
yield return 888;
yield return 999;
}
}
}
三、迭代器的内部状态
迭代器在编译器生成的枚举器中,没有实现Reset方法,所以不可以调用Reset。在后台编译器把迭代器转换为的枚举器类包含4个状态:
Before 首次调用MoveNext之前的状态
Running 调用MoveNext后进入这个状态
Supended 状态机等待下次调用MoveNext的状态
After 没有更多项可枚举
四、迭代器与异常处理#
yield return语句不可以出现在try/catch/finally语句块中。原因是:迭代器在编译阶段会转为私有类型放在这些语句块中会导致异常复杂。但是可以放在try/finally语句块中。
实例:迭代器的异常处理
IEnumerable<string> Foo()
{
try { yield return "One"; } // OK
finally { ... }
}
作者:重庆熊猫
出处:https://www.cnblogs.com/cqpanda/p/16153337.html
版权:本作品采用「不论是否商业使用都不允许转载,否则按3元1字进行收取费用」许可协议进行许可。
本文来自博客园,作者:重庆熊猫,转载请注明原文链接:https://www.cnblogs.com/cqpanda/p/16153337.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义