當你建立一個類別表現得像集合時,支援 foreach 迴圈遍歷會大幅提升使用體驗。C# 1.1 需手動實作 IEnumerable/IEnumerator 介面,C# 2.0 引入 yield return 大幅簡化實作。本文將從傳統模式開始,逐步演進到現代寫法。
內部使用固定大小陣列儲存字串,提供 Add 與 GetNumEntries 方法:
public class ListBox
{
private string[] strings = new string[8];
private int count = 0;
public ListBox(params string[] initialStrings)
{
foreach (string s in initialStrings)
{
strings[count++] = s;
}
}
public void Add(string theString)
{
strings[count++] = theString;
}
public int GetNumEntries() => count;
}
public IEnumerator GetEnumerator()
{
return new ListBoxEnumerator(this);
}
private class ListBoxEnumerator : IEnumerator
{
private ListBox listBox;
private int index = -1;
public ListBoxEnumerator(ListBox lb)
{
listBox = lb;
}
public object Current => listBox.strings[index];
public bool MoveNext()
{
if (index < listBox.count - 1)
{
index++;
return true;
}
return false;
}
public void Reset() => index = -1;
}
ListBox lb = new ListBox("Hello", "World");
lb.Add("Who");
lb.Add("Is");
lb.Add("John");
lb.Add("Galt");
foreach (string s in lb)
{
Console.WriteLine("Value: {0}", s);
}
// 輸出:
// Hello
// World
// Who
// Is
// John
// Galt
| 介面 | 角色 | 核心成員 |
|---|---|---|
| IEnumerable | 可列舉物件 | GetEnumerator() : IEnumerator |
| IEnumerator | 列舉器/游標 | Current, MoveNext(), Reset() |
注意:IEnumerable 與 IEnumerator 是不同介面,前者代表「可被列舉的容器」,後者代表「列舉過程中的游標」。
最佳實務是在 IEnumerable 類別內部定義 private class Enumerator : IEnumerator:
下一篇將介紹 C# 2.0 的革命性簡化:
yield return 自動產生列舉器IEnumerable<T> 與 IEnumerator<T>