|
系列文章導航:
不能不說的C#特性-迭代器(下),yield以及流的延遲計算
走進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-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;
}
系列文章導航:
不能不說的C#特性-迭代器(下),yield以及流的延遲計算
走進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-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 (
[0] int32 i,
[1] class [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
}
系列文章導航:
不能不說的C#特性-迭代器(下),yield以及流的延遲計算
走進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-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以及流的延遲計算,轉載需保留來源!
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。