鼎鼎知识库
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

22.yield语句.md 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. **用yield return 语句实现一个简单结合**
  2. - HelloCollection 类包括GetEnumerator()方法。该方法的实现代码包含两条yield return语句,它们分别返回字符串Hello和World
  3. ```
  4. using System;
  5. using System.Collections;
  6. namepace Wrox.ProCSharp.Arrays
  7. {
  8. public class HelloCollection
  9. {
  10. public IEnumerator<string>GetEnumerator()
  11. {
  12. yield return"HEllo";
  13. yield return "World";
  14. }
  15. }
  16. }
  17. 现在可以用foreach语句迭代集合
  18. public void HelloWord()
  19. {
  20. var helloCollection=new HelloCollection();
  21. foreach(var s in helloCollection)
  22. {
  23. WriteLine(s);
  24. }
  25. }
  26. ```
  27. -包含yield 语句的方法或属性也称为迭代块。迭代块必须声明为返回IEnumerator或IEnumerable接口,或者这些接口的泛型版本,这个块可以包含多条yield return语句或yield break 语句,但不能包含return语句。
  28. - 下面例子,可以把yield类型看做内部类Enumerator。外部类的GEtEnumerator()方法实例化并返回一个新的yield类型。在yield类型中,变量state定义了迭代的当前位置,每次调用MoveNext()时,当前位置都会改变。MoveNext()封装了迭代块的代码,并设置了current变量的值,从此使Current属性根据位置返回一个对象。
  29. ```
  30. public class HelloCollection
  31. {
  32. public IEnumerator GetEnumerator()=>new Enumerator(0);
  33. public class Enumerator :IEnumerator<string>,IEnumerator,IDisposable
  34. {
  35. private int_state;
  36. private string _current;
  37. public Enumerator(int state)
  38. {
  39. _state =state;
  40. }
  41. bool System.Collections.IEnumerator.MoveNext()
  42. {
  43. switch(state)
  44. {
  45. case 0:
  46. _current="Hello";
  47. _state=1;
  48. return true;
  49. case 1:
  50. _current="World";
  51. _state=2;
  52. return true;
  53. case 2:
  54. break;
  55. }
  56. return false;
  57. }
  58. void System.Collections.IEnumerator.Reset()
  59. {
  60. throw new NotSupportedException();
  61. }
  62. string System.Collections.Generic.IEnumerator<string>.Current=>current;
  63. void IDisposable.Dispose()
  64. {}
  65. }
  66. }
  67. ```
  68. > 用yield return 返回枚举器
  69. - 例子说明:在Tic-Tac-Toe 游戏中有9个域,玩家轮流在这些域中放置一个“十”字或一个圆。这些移动操作由GameMoves类模拟。方法Cross()和Circle()是创建迭代类型的迭代块。在Cross()迭代块中,将移动操作的信息写到控制台上,并递增移动次数。如果移动次数大于8,就用yield break停止迭代;否则,就在每次迭代中返回yield类型circle的枚举对象。Circle()迭代块非常类似于Cross()迭代块,知识它在每次迭代中返回cross迭代器类型
  70. ```
  71. public class GameMoves
  72. {
  73. private IEnumerator _cross;
  74. private IEnumerator _circle;
  75. public GameMoves()
  76. {
  77. _cross=Cross();
  78. _circle=Circle();
  79. }
  80. private int _move=0;
  81. const int MAxMoves=9;
  82. public IEnumerator Cross()
  83. {
  84. while (true)
  85. {
  86. WriteLine($"Cross,move {_move}");
  87. if(++_move >=MaxMoves)
  88. {
  89. yield break;
  90. }
  91. yield return _circle;
  92. }
  93. }
  94. public IEnumerator Circle()
  95. {
  96. while(true)
  97. {
  98. WriteLine($"Circle,move{move}");
  99. if(++_move>=MaxMoves)
  100. {
  101. yield break;
  102. }
  103. yield return _cross;
  104. }
  105. }
  106. }
  107. ```