close
首先, 以ArrayList為例,透過foreach指令來依序讀取內容物
1: ArrayList list = new ArrayList();
2: list.Add("1");
3: list.Add(2);4: list.Add("3");
5: list.Add('4');
6: foreach(object o in list)
7: {8: Console.Write($"{o.GetType().ToString()} :");
9: Console.WriteLine(o); 10: }假設我們有一個簡單的函式如下,希望每次呼叫依序回傳1, 2, 3…
1: static int SimpleReturn()
2: {3: return 1;
4: return 2;
5: return 3;
6: }如果用下列方式呼叫SimpleReturn()
1: static void Demo4()
2: { 3: Console.WriteLine(SimpleReturn()); 4: Console.WriteLine(SimpleReturn()); 5: Console.WriteLine(SimpleReturn()); 6: Console.WriteLine(SimpleReturn()); 7: }似乎只會回傳遞一種結果
如果將SimpleReturn修改成YieldReturn()如下
1: static IEnumerable<int> YieldReturn()
2: {3: yield return 1;
4: yield return 2;
5: yield return 3;
6: }用下列方式呼叫YieldReturn()
1: static void Demo5()
2: {3: foreach(int i in YieldReturn())
4: Console.WriteLine(i); 5: }結果如下,可以依序取出1, 2, 3,…
-------------------------------------------------------------------------------------------------------------------------------
1. MyArrayList 繼承 IEnumerable介面,其中GetEnumerator()需要自行實作。
1: class MyArrayList : IEnumerable
2: {3: public IEnumerator GetEnumerator()
4: {5: throw new NotImplementedException();
6: } 7: }2. 建立MyArrayList 私有變數成員(m_items、index)及創建子
1: class MyArrayList : IEnumerable
2: {3: // 儲存陣列
4: object[] m_items = null;
5: // 陣列索引
6: int index = 0;
7: 8: /// <summary>
9: /// MyArrayList創建子
10: /// </summary>
11: public MyArrayList()
12: {13: // For the sake of simplicity lets keep them as arrays
14: // ideally it should be link list
15: m_items = new object[100];
16: }17: public IEnumerator GetEnumerator()
18: {19: throw new NotImplementedException();
20: } 21: }3. 加入public method: Add() 提供物件加入陣列
1: public void Add(object item)
2: { 3: m_items[index] = item; 4: index++; 5: }
4. 重新定義GetEnumerator:
如同前面YieldReturn()例子, 我們希望提供一個method每呼叫一次,可以取得m_items的一個元素,
並且索引值自動移動至下一個元素(yield), 下次呼叫則傳回該索引值所指的元素(return),重複這些動作直到取完為止(o==null)。
1: public IEnumerator GetEnumerator()
2: {3: foreach(object o in m_items)
4: {5: // Lets check for end of list (its bad code since we used arrays)
6: if (o==null)
7: {8: break;
9: }10: // Return the current element and then on next function call
11: // resume from next element rather than starting all over again;
12: yield return o;
13: } 14: }
綜合1~4程式碼
1: class MyArrayList : IEnumerable
2: {3: // 儲存陣列
4: object[] m_items = null;
5: // 陣列索引
6: int index = 0;
7: 8: /// <summary>
9: /// MyArrayList創建子
10: /// </summary>
11: public MyArrayList()
12: {13: // For the sake of simplicity lets keep them as arrays
14: // ideally it should be link list
15: m_items = new object[100];
16: } 17: 18: public void Add(object item)
19: { 20: m_items[index] = item; 21: index++; 22: }23: public IEnumerator GetEnumerator()
24: {25: foreach(object o in m_items)
26: {27: // Lets check for end of list (its bad code since we used arrays)
28: if (o==null)
29: {30: break;
31: }32: // Return the current element and then on next function call
33: // resume from next element rather than starting all over again;
34: yield return o;
35: } 36: } 37: }MyArrayList範例:
1: static void Demo6()
2: {3: MyArrayList myArrayList = new MyArrayList();
4: 5: myArrayList.Add("1");
6: myArrayList.Add(2);7: myArrayList.Add("3");
8: myArrayList.Add('4');
9: foreach (object s in myArrayList)
10: { 11: Console.WriteLine(s); 12: } 13: }接下來,加入泛型: MyList
1: class MyList<T> : IEnumerable<T>
2: { 3: // 儲存陣列
4: T[] m_Items = null;
5: // 陣列索引
6: int index = 0;
7: public MyList()
8: {9: // For the sake of simplicity lets keep them as arrays
10: // ideally it should be link list
11: m_Items = new T[100];
12: }13: public void Add(T item)
14: {15: // Let us only worry about adding the item
16: m_Items[index] = item; 17: index++; 18: } 19: 20: public IEnumerator<T> GetEnumerator()
21: {22: foreach(T o in m_Items)
23: {24: // Lets check for end of list (its bad code since we used arrays)
25: if (o==null)
26: {27: break;
28: }29: // Return the current element and then on next function call
30: // resume from next element rather than starting all over again;
31: yield return m_Items[index];
32: } 33: } 34: 35: IEnumerator IEnumerable.GetEnumerator() 36: {37: // Lets call the generic version here
38: return this.GetEnumerator();
39: } 40: }MyList範例:
1: // Let us first see how we can enumerate an custom MyList<t> class implementing IEnumerable<T>
2: MyList<string> myListOfStrings = new MyList<string>();
3: 4: myListOfStrings.Add("one");
5: myListOfStrings.Add("two");
6: myListOfStrings.Add("three");
7: myListOfStrings.Add("four");
8: 9: foreach (string s in myListOfStrings)
10: { 11: Console.WriteLine(s); 12: }
1. 利用while()搭配yield指令,每次呼叫GetRandIntSub()吐出一個隨機整數值,其格式為IEnumerable<int>
1: private static IEnumerable<int> GetRandIntSub(int range)
2: {3: while(true)
4: {5: Random r = new Random();
6: yield return r.Next() % range;
7: } 8: }2. 再利用foreach去接收IEnumerable<int>的東西
1: private static int GetRandInt()
2: {3: int range = 10;
4: int output = 0;
5: foreach(int val in GetRandIntSub(range))
6: { 7: output = val;8: return output;
9: }10: return output;
11: }3. 呼叫GetRandInt()
1: private static void Demo8()
2: {3: IList<int> myList = new List<int>();
4: for (int i = 0; i < 10; i++)
5: { 6: myList.Add(GetRandInt());7: Console.WriteLine($"length: {myList.Count}");
8: Console.WriteLine($"value: {myList[myList.Count - 1]}");
9: Thread.Sleep(100); 10: } 11: }結果如下:
參考資料:
1. A Beginner's Tutorial on Implementing IEnumerable Interface and Understanding yield Keyword
全站熱搜





留言列表
