yield
如何實施lazy loading
的模式?yield如何實現延遲加載的模式?
回答
收益實現直到需要時纔會到達代碼。
例如,下面的代碼:
public IEnumerable<int> GetInts()
{
yield return 1;
yield return 2;
yield return 3;
}
將實際編譯成執行IEnumerable<int>
和GetInts()
身體會返回一個類的實例嵌套類。
使用反射鏡可以看到:
public IEnumerable<int> GetInts()
{
<GetInts>d__6d d__d = new <GetInts>d__6d(-2);
d__d.<>4__this = this;
return d__d;
}
編輯 - 增加更多的信息關於GetInts
實現:
此實現使得懶惰是基於Enumerator
MoveNext()
方法的方式。生成可枚舉的嵌套類(示例中的<GetInts>d__6d
)時,它具有一個狀態,並且每個狀態都連接一個值(這是一個簡單的例子,在更高級的情況下,代碼到達狀態時將評估該值)。如果我們採取的<GetInts>d__6d
的MoveNext()
代碼一看,我們會看到狀態:
private bool MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<>2__current = 1;
this.<>1__state = 1;
return true;
case 1:
this.<>1__state = -1;
this.<>2__current = 2;
this.<>1__state = 2;
return true;
case 2:
this.<>1__state = -1;
this.<>2__current = 3;
this.<>1__state = 3;
return true;
case 3:
this.<>1__state = -1;
break;
}
return false;
}
當枚舉被要求爲當前對象返回連接到當前狀態的對象。
爲了表明,只有當它需要你可以看看下面這個例子的代碼進行評估:
[TestFixture]
public class YieldExample
{
private int flag = 0;
public IEnumerable<int> GetInts()
{
yield return 1;
flag = 1;
yield return 2;
flag = 2;
yield return 3;
flag = 3;
}
[Test]
public void Test()
{
int expectedFlag = 0;
foreach (var i in GetInts())
{
Assert.That(flag, Is.EqualTo(expectedFlag));
expectedFlag++;
}
Assert.That(flag, Is.EqualTo(expectedFlag));
}
}
我希望這是更清晰一點。我建議使用Reflector來查看代碼,並在更改「yield」代碼時觀察編譯的代碼。
如果您想了解更多關於什麼編譯器使用yield return
這樣做的時候,檢查這篇文章喬恩斯基特:Iterator block implementation details
Briljant重定向,實際上。 +1 – peSHIr 2010-05-03 10:20:03
基本上迭代器使用yield
語句implementated被編譯成一個實現state machine類。
如果您從不foreach
(=迭代並實際使用)返回的IEnumerable<T>
,代碼永遠不會實際執行。如果你這樣做,只需要確定下一個返回值所需的最小代碼就可以執行,只有當請求下一個值時才能恢復執行。
當您在調試器中單步執行此類代碼時,您實際上可以看到此行爲發生。至少嘗試一次:我認爲這是一步一步發生的。
- 1. 如何實現延遲加載文本
- 2. 延遲加載實現的問題
- 3. 加載彈出模式的延遲
- 4. 模式的延遲加載與Python
- 5. 隱式延遲加載vs顯式延遲加載
- 6. 存儲庫模式:模型關係的實現和延遲加載
- 7. 在VBScript中實現延遲加載的模塊
- 8. 對實體延遲加載
- 9. 如何實現容器類的延遲加載?
- 10. 如何在UITableView中實現類似UIImageView的延遲加載
- 11. 如何實現延遲加載的屬性
- 12. 如何在角4.3.1中實現嵌套的延遲加載?
- 13. 延遲加載組織模式
- 14. 延遲加載延遲
- 15. 如何以RESTful方式「延遲加載」?
- 16. 延遲加載模型
- 17. 如何延遲加載?
- 18. 如何使用Spring數據JPA(JPARepository)實現延遲加載?
- 19. 如何使用RequireJS實現延遲加載?
- 20. 如何使用SQLite實現延遲加載?
- 21. 如何在Vaadin中實現延遲加載樹?
- 22. 如何使用PostSharp實現延遲加載?
- 23. 如何在Tapestry中實現延遲區域重新加載?
- 24. 如何在GridView中實現延遲加載圖像
- 25. 如何在Angular中實現延遲加載動態img src
- 26. 如何實現延遲加載到uiscroll視圖
- 27. 如何使用jQuery延遲對象實現預加載程序
- 28. 如何在elixir中實現延遲模式?
- 29. 實體框架延遲加載和DTO模式
- 30. 延遲加載
@Elisha:請提供關於GetInts()的更多詳細信息。 – 2010-05-03 10:53:54
@masoud ramezani,增加了關於GetInts嵌套枚舉類的更多信息。 – Elisha 2010-05-03 13:52:38
謝謝你的完整答案。 – 2010-05-03 14:22:36