关于C#之yield return 话题
还是先来个具体的实例吧:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace yeildTST
{
public class List
{
public static IEnumerable Power(int number)
{
while (number< 100)
{
number = number + number;
yield return number;
}
}
static void Main()
{
foreach (int i in Power(1))
{
Console.Write("{0} ", i);
}
Console.ReadLine();
}
}
我们来通过这个例子看看yield return的庐山真面目,我查了下原始编译代码:
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace yeildTST
{
public class List
{
public static IEnumerable Power(int number)
{
while (number< 100)
{
number = number + number;
yield return number;
}
}
static void Main()
{
foreach (int i in Power(1))
{
Console.Write("{0} ", i);
}
Console.ReadLine();
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace yeildTST
{
public class List
{
static void Main()
{
foreach (int i in Power(1))
{
Console.Write("{0} ", i);
}
Console.ReadLine();
}
public static IEnumerable Power(int number)
{
d__0 d__ = new d__0(-2);
d__._3__number = number;
return d__;
}
//// Nested Types
//[CompilerGenerated]
public class d__0 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable
{
// Fields
private int _1__state;
private object _2__current;
public int _3__number;
private int _l__initialThreadId;
public int number;
// Methods
//[DebuggerHidden]
public d__0(int _1__state)
{
this._1__state = _1__state;
this._l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
}
public bool MoveNext()
{
switch (this._1__state)
{
case 1:
// goto label_057;-----生成的源代码
//////////我修改后的代码,原来没有//////
_1__state = -1;
while (this.number < 100)
{
this.number += this.number;
this._2__current = this.number;
this._1__state = 1;
return true;
}
break;
///////////////////////////////
case 0:
this._1__state = -1;
while (this.number < 100)
{
this.number += this.number;
this._2__current = this.number;
this._1__state = 1;
//label_****: -----生成的源代码
//this._1__state=-1;
return true;
}
break;
}
return false;
}
//[DebuggerHidden]
IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
return null;////////不用到这个,所以代码去掉了。
}
//[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
List.d__0 d__;
if ((Thread.CurrentThread.ManagedThreadId == this._l__initialThreadId) && (this._1__state == -2))
{
this._1__state = 0;
d__ = this;
}
else
{
d__ = new List.d__0(0);
}
d__.number = this._3__number;
return d__;
}
//[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
void IDisposable.Dispose()
{
}
// Properties
object IEnumerator<object>.Current
{
// [DebuggerHidden]
get
{
return this._2__current;
}
}
object IEnumerator.Current
{
//[DebuggerHidden]
get
{
return this._2__current;
}
}
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace yeildTST
{
public class List
{
static void Main()
{
foreach (int i in Power(1))
{
Console.Write("{0} ", i);
}
Console.ReadLine();
}
public static IEnumerable Power(int number)
{
d__0 d__ = new d__0(-2);
d__._3__number = number;
return d__;
}
//// Nested Types
//[CompilerGenerated]
public class d__0 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable
{
// Fields
private int _1__state;
private object _2__current;
public int _3__number;
private int _l__initialThreadId;
public int number;
// Methods
//[DebuggerHidden]
public d__0(int _1__state)
{
this._1__state = _1__state;
this._l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
}
public bool MoveNext()
{
switch (this._1__state)
{
case 1:
// goto label_057;-----生成的源代码
//////////我修改后的代码,原来没有//////
_1__state = -1;
while (this.number < 100)
{
this.number += this.number;
this._2__current = this.number;
this._1__state = 1;
return true;
}
break;
///////////////////////////////
case 0:
this._1__state = -1;
while (this.number < 100)
{
this.number += this.number;
this._2__current = this.number;
this._1__state = 1;
//label_****: -----生成的源代码
//this._1__state=-1;
return true;
}
break;
}
return false;
}
//[DebuggerHidden]
IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
return null;////////不用到这个,所以代码去掉了。
}
//[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
List.d__0 d__;
if ((Thread.CurrentThread.ManagedThreadId == this._l__initialThreadId) && (this._1__state == -2))
{
this._1__state = 0;
d__ = this;
}
else
{
d__ = new List.d__0(0);
}
d__.number = this._3__number;
return d__;
}
//[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
void IDisposable.Dispose()
{
}
// Properties
object IEnumerator<object>.Current
{
// [DebuggerHidden]
get
{
return this._2__current;
}
}
object IEnumerator.Current
{
//[DebuggerHidden]
get
{
return this._2__current;
}
}
}
}
}
仔细看这段代码,多了一个类,d_0,它实现了各种枚举接口,由于我们的例题没有用到泛型,所以新生成的代码中
泛型部分可省去,经过我的测试,它对类中执行方法的顺序是这样的:
开始
GetEnumerator() => MoveNext() => IEnumerator.Current
第二次,从MoveNext() => IEnumerator.Current 。。。。。。。直到循环完成。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述