不能不说的C#特性-迭代器(下),yield以及流的延迟计算

系列文章导航:

走进Linq--Linq横空出世篇

走进Linq-辉煌的背后

走进Linq-Linq大观园

不能不说的C#特性-对象集合初始化器

不能不说的C#特性-匿名类型与隐式类型局部变量

不能不说的C#特性-扩展方法

不能不说的C#特性-匿名方法和Lambda表达式

不能不说的C#特性-迭代器(上)及一些研究过程中的副产品

不能不说的C#特性-迭代器(下),yield以及流的延迟计算

走进Linq-Linq to Objects(上)基础篇

走进Linq-Linq to Objects(下)实例篇

走进Linq-Linq to SQL感性认识篇

走进Linq-Linq to SQL How do I(1)

走进Linq-Linq to SQL How do I(2)

走进Linq-Linq to SQL How do I(3)

走进Linq-How do I(4)拾遗补零篇第一节

走进Linq-Linq to SQL源代码赏析 Table的获取过程

走进Linq-Linq to SQL源代码赏析之Provider的初始化

走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq


题目:从0遍历到20(不包括20),输出遍历到的每个元素,并将大于2的所有数字放到一个IEnumerable中返回

解答1:(我以前经常这样做)

static IEnumerable<int> WithNoYield()
        {
            IList
<int> list = new List<int>();
            
for (int i = 0; i < 20; i++)
            {
                Console.WriteLine(i.ToString());
                
if(i > 2)
                    list.Add(i);
            }
            
return list;
        }

系列文章导航:

走进Linq--Linq横空出世篇

走进Linq-辉煌的背后

走进Linq-Linq大观园

不能不说的C#特性-对象集合初始化器

不能不说的C#特性-匿名类型与隐式类型局部变量

不能不说的C#特性-扩展方法

不能不说的C#特性-匿名方法和Lambda表达式

不能不说的C#特性-迭代器(上)及一些研究过程中的副产品

不能不说的C#特性-迭代器(下),yield以及流的延迟计算

走进Linq-Linq to Objects(上)基础篇

走进Linq-Linq to Objects(下)实例篇

走进Linq-Linq to SQL感性认识篇

走进Linq-Linq to SQL How do I(1)

走进Linq-Linq to SQL How do I(2)

走进Linq-Linq to SQL How do I(3)

走进Linq-How do I(4)拾遗补零篇第一节

走进Linq-Linq to SQL源代码赏析 Table的获取过程

走进Linq-Linq to SQL源代码赏析之Provider的初始化

走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq


测试1的运算结果

测试WithNoYield():输出从0-19的数字

测试WithYield():什么都不输出

测试2的运算结果

测试WithNoYield():输出1-19接着输出3-19

测试WithYield():输出12334455…….

(为节省空间上面的答案没有原样粘贴,可以自己运行测试)

是不是感到很奇怪,为什么使用了yield的程序表现的如此怪异呢?

测试1中对WithYield()的测试,明明方法调用了,居然一行输出都没有,难道for循环根本没有执行?通过断点调试果然如此,for循环根本没有进去,这是咋回事?测试2中对WithYield()的测试输出是有了,不过输出怎么这么有趣?穿插着输出,在foreach遍历WithYield()的结果的时候,好像不等到最后一条遍历完,WithYield()不退出,这又是怎么回事?

还是打开IL代码瞧一瞧到底发生了什么吧

Main方法的IL代码:

.method private hidebysig static void Main() cil managed
{
    
.entrypoint
    
.maxstack 1
    
.locals init (
        [
0int32 i,
        [
1class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> CS$5$0000)
    
L_0000: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> TestLambda.Program::WithYield()
    
L_0005: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`10> [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
    
L_000a: stloc.1 
    
L_000b: br.s L_0020
    
L_000d: ldloc.1 
    
L_000e: callvirt instance !0 [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
    
L_0013: stloc.0 
    
L_0014: ldloca.s i
    
L_0016: call instance string [mscorlib]System.Int32::ToString()
    
L_001b: call void [mscorlib]System.Console::WriteLine(string)
    
L_0020: ldloc.1 
    
L_0021: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
    
L_0026: brtrue.s L_000d
    
L_0028: leave.s L_0034
    
L_002a: ldloc.1 
    
L_002b: brfalse.s L_0033
    
L_002d: ldloc.1 
    
L_002e: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    
L_0033: endfinally 
    
L_0034: call string [mscorlib]System.Console::ReadLine()
    
L_0039: pop 
    
L_003a: ret 
    .try L_000b to L_002a finally handler L_002a to L_0034
}

系列文章导航:

走进Linq--Linq横空出世篇

走进Linq-辉煌的背后

走进Linq-Linq大观园

不能不说的C#特性-对象集合初始化器

不能不说的C#特性-匿名类型与隐式类型局部变量

不能不说的C#特性-扩展方法

不能不说的C#特性-匿名方法和Lambda表达式

不能不说的C#特性-迭代器(上)及一些研究过程中的副产品

不能不说的C#特性-迭代器(下),yield以及流的延迟计算

走进Linq-Linq to Objects(上)基础篇

走进Linq-Linq to Objects(下)实例篇

走进Linq-Linq to SQL感性认识篇

走进Linq-Linq to SQL How do I(1)

走进Linq-Linq to SQL How do I(2)

走进Linq-Linq to SQL How do I(3)

走进Linq-How do I(4)拾遗补零篇第一节

走进Linq-Linq to SQL源代码赏析 Table的获取过程

走进Linq-Linq to SQL源代码赏析之Provider的初始化

走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq


private bool MoveNext()
    {
        
switch (this.<>1__state)
        {
            
case 0:
                
this.<>1__state = -1;
                
this.<i>5__1 = 0;
                
goto Label_006A;

            
case 1:
                
this.<>1__state = -1;
                
goto Label_005C;

            
default:
                
goto Label_0074;
        }
    Label_005C:
        
this.<i>5__1++;
    Label_006A:
        
if (this.<i>5__1 < 20)
        {
            Console.WriteLine(
this.<i>5__1.ToString());
            
if (this.<i>5__1 > 2)
            {
                
this.<>2__current = this.<i>5__1;
                
this.<>1__state = 1;
                
return true;
            }
            
goto Label_005C;
        }
    Label_0074:
        
return false;
    }

it知识库不能不说的C#特性-迭代器(下),yield以及流的延迟计算,转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。