2015-05-29 49 views
0

我正在學習基本的C# 我有下面的代碼片段翻譯產量的回報

while(p!=null) 
{ 
    foreach(var x in X) 
     yield return x; 
    //.... 
    foreach(var y in Y) 
     yield return y; 
    p=GetP(); 
} 

是上述相同的代碼

IEnumerable<object> os; 
while (p!=null) 
{ 
    foreach(var x in X) 
     os.Add(x); 
    //.... 
    foreach(var y in Y) 
     os.Add(y); 
    p=GetP(); 
} 
return os; 

???

+1

技術上不行,因爲你不能直接創建一個'IEnumerable ',所以第二個例子將不起作用。無論哪種方式,第一個示例按順序返回項,先是'X',然後是'Y',然後調用'GetP',而第二個示例將它們全部添加到枚舉器並調用'GetP'。第一個可能會改變'GetP'返回的結果,並可能給出不同的結果。 –

+0

'IEnumerable <>'沒有'add'方法,所以你不能通過引用'os'添加它。 – Rob

回答

4

這兩個代碼片段*只是在它們如果迭代完成才能產生相同的對象序列的意義上是「相同的」。但是,迭代過程中發生的實際順序是非常不同的。

yield return
  • 代碼可以被提前終止,如果迭代所得IEnumerable循環終止一個break或異常的早期,因爲。
  • 添加到集合中的代碼會在內存中準備新的集合。代碼yield return使用現有的集合來創建可迭代的序列,而不將結果存儲在內存中。
  • 帶有yield return的代碼可以對迭代過程中迭代的變化做出反應。例如,如果使用yield return方法的代碼在迭代X的過程中添加到集合Y,那麼當迭代Y時,將返回新項目。第二個代碼示例將無法做到這一點。

*讓我們假設IEnumerable<T>Add方法;在現實中,你可能最終會使用List<T>或其他一些集合。

0

我相信你在收益率工作的一般方式上是正確的。產量應該稍微多一點,而不僅僅是添加到集合中,因爲只有在需要時才能訪問。

MSDN

您使用yield return語句每個元素一次一個返回。

您使用foreach語句或LINQ查詢來使用迭代器方法。 foreach循環的每次迭代調用迭代器方法。在迭代器方法中達到yield return語句時,將返回expression,並保留代碼中的當前位置。下一次調用迭代器函數時,將從該位置重新啓動執行。