1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); // IEnumerable // GetEnumerator()の返値はIEnumerator // 反復子が使える // IEnumerator // Current, MoveNext(), Reset() var test = new Test(new string[] { "a", "b", "c" }); foreach (var t in test) { MessageBox.Show(t); // a, b, c } } } public class Test : IEnumerable<string> { private string[] stringList; public Test(string[] s) { stringList = s; } public IEnumerator<string> GetEnumerator() { return new MyEnumerator(stringList); // こちらが呼ばれている } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); // こちらは呼ばれない // IEnumerator<T>がIEnumeratorを継承しているため両方のGetEnumeratorが必要 } } public class MyEnumerator: IEnumerator<string> { int p = -1; string[] stringList; public MyEnumerator(string[] s) { stringList = s; } string IEnumerator<string>.Current { get { return stringList[p]; } } object IEnumerator.Current { get { return stringList[p]; } } void IDisposable.Dispose() { } bool IEnumerator.MoveNext() { p++; if (p >= stringList.Length) { return false; } return true; } void IEnumerator.Reset() { p = -1; } } |
C#2.0からイテレータ構文が導入され簡単に実装できるようなった。
戻り値は、IEnumerableを返す必要がある。
yield returnは処理を継続、yield breakはそこで処理が終了する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); foreach (var s in TestMethod()) { MessageBox.Show(s); } } public IEnumerable<string> TestMethod() { yield return "Hello"; yield return "World"; } } |