![](/img/trans.png)
[英]What is the difference (if any) between “yield” and “yield return” in C#?
[英]What is the exact difference between returning an IEnumerable instance and the yield return statement in C#
目前我正在使用一些通過迭代器應用延遲執行的庫。 在某些情況下,我需要簡單地“轉發”收到的迭代器。 即我必須從被調用的方法獲取IEnumerable<T>
實例並立即返回它。
現在我的問題:簡單地返回收到的IEnumerable<T>
或通過循環重新產生它之間是否存在相關區別?
IEnumerable<int> GetByReturn()
{
return GetIterator(); // GetIterator() returns IEnumerable<int>
}
// or:
IEnumerable<int> GetByReYielding()
{
for(var item in GetIterator()) // GetIterator() returns IEnumerable<int>
{
yield return item;
}
}
閱讀Jon Skeet關於C#迭代器的文章可能值得你去參考。 這是非常有益的。
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
它們是不同的。 例如,如果GetIterator()
聲明為:
IEnumerable<int> GetIterator() {
List<int> result = new List<int>();
for(int i = 0; i < 1000; i++) {
result.Add(i);
}
return result;
}
如果不進行重新生成, GetIterator()
立即執行GetIterator()
和循環。 因此,答案取決於您如何實現GetIterator()
。 如果確定GetIterator()
將會屈服,那么重新產生它就沒有意義了。
除了代碼膨脹之外,我沒有看到任何相關的區別。
兩者之間沒有任何相關的差異(除了可能的性能),因為你沒有使用GetIterator()
的枚舉器做任何事情。 如果您要對枚舉器執行某些操作(例如過濾器),那么重新收益才有意義。
有一個相關的區別。
GetByReYielding()的執行將以延遲方式執行(因為它是迭代器塊)。 如果您在GetByReturn()或GetByReYielding()中使用了一個參數並在運行時檢查該參數是否為null(或進行了任何其他驗證),則在調用GetByReturn()時立即執行此檢查,但在調用GetByReYielding()時不立即執行此檢查! 當迭代結果時,GetByReYielding()中的驗證將以延遲方式執行。 - 這通常是“太晚了”。 看這里:
// Checks parameters early. - Fine. The passed argument will be checked directly when
// GetByReturn() is called.
IEnumerable<int> GetByReturn(IEnumerable<int> sequence)
{
if(null == sequence)
{
throw new ArgumentNullException("sequence");
}
return GetIterator();
}
// Checks parameters in a deferred manner. - Possibly not desired, it's "too" late. I.e. // when the
// result is iterated somewhere in a completely different location in your code the
// argument passed once will be checked.
IEnumerable<int> GetByReYielding(IEnumerable<int> sequence)
{
if(null == sequence)
{
throw new ArgumentNullException("sequence");
}
for(var item in GetIterator())
{
yield return item;
}
}
Skeet先生在http://msmvps.com/blogs/jon_skeet/archive/2010/09/03/reimplementing-linq-to-objects-part-2-quot-where-quot.aspx中解釋了這個概念。 .Net中提供的標准查詢運算符使用非延遲包裝函數(例如Where())來檢查參數,然后調用核心迭代器函數(正如我在GetByReturn()的實現中所示)。
我希望這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.