2011-10-13 95 views
4

在下面的測試中,使用yield return時無法使Console.WriteLine真正打印。 我正在嘗試收益回報,並且我明白我的理解中缺少某些東西,但無法找到它是什麼。爲什麼不在PrintAllYield內打印字符串?無法使用收益率返回打印到控制檯

代碼:

class Misc1 { 
    public IEnumerable<string> PrintAllYield(IEnumerable<string> list) { 
     foreach(string s in list) { 
      Console.WriteLine(s); // doesn't print 
      yield return s; 
     } 
    } 
    public void PrintAll(IEnumerable<string> list) { 
     foreach(string s in list) { 
      Console.WriteLine(s); // surely prints OK 
     } 
    } 
} 

測試:

[TestFixture] 
class MiscTests { 
    [Test] 
    public void YieldTest() { 
     string[] list = new[] { "foo", "bar" }; 
     Misc1 test = new Misc1(); 

     Console.WriteLine("Start PrintAllYield"); 
     test.PrintAllYield(list); 
     Console.WriteLine("End PrintAllYield"); 

     Console.WriteLine(); 

     Console.WriteLine("Start PrintAll"); 
     test.PrintAll(list); 
     Console.WriteLine("End PrintAll"); 
    } 
} 

輸出:

Start PrintAllYield 
End PrintAllYield 

Start PrintAll 
foo 
bar 
End PrintAll 

1 passed, 0 failed, 0 skipped, took 0,39 seconds (NUnit 2.5.5). 

回答

11

你有實際枚舉返回IEnumerable看到輸出:

Console.WriteLine("Start PrintAllYield"); 
    foreach (var blah in test.PrintAllYield(list)) 
     ; // Do nothing 
    Console.WriteLine("End PrintAllYield"); 

當您使用yield return關鍵字時,編譯器將爲您構建一個狀態機。它的代碼只有在你實際使用它迭代返回的枚舉時纔會運行。

是否有什麼特別的原因您試圖用yield return打印出string s的序列?這不是真正的功能的目的,這是爲了簡化序列生成器的創建,而不是枚舉已經生成的序列。 foreach是後者的首選方法。

+0

謝謝,我現在明白了。所以調用PrintAllYield只會構造狀態機,但是在返回的枚舉被迭代時執行主體。 – henginy

+0

@henginy沒錯。每當你在返回的對象上調用MoveNext()時,它都會運行,直到它達到「yield return」(或「yield break」)。 – dlev

+0

謝謝。順便說一下,我的實際目的不是打印字符串,而是僅用於調試目的。實際的代碼掃描目錄並處理它們中的文件。我使用yield return來建立流式執行的管道。 – henginy