// 非泛型
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
// 泛型 (推薦)
public interface IEnumerable : IEnumerable
{
IEnumerator GetEnumerator();
}
public interface IEnumerator : IDisposable, IEnumerator
{
T Current { get; }
}
using System;
using System.Collections;
public class ColorEnumerator : IEnumerator
{
private readonly string[] _colors;
private int _position = -1;
public ColorEnumerator(string[] colors)
{
_colors = new string[colors.Length];
Array.Copy(colors, _colors, colors.Length);
}
public object Current
{
get
{
if (_position == -1 || _position >= _colors.Length)
throw new InvalidOperationException("枚舉器位於無效位置");
return _colors[_position];
}
}
public bool MoveNext()
{
if (_position < _colors.Length - 1)
{
_position++;
return true;
}
return false;
}
public void Reset() => _position = -1;
}
public class ColorCollection : IEnumerable
{
private readonly string[] _colors;
public ColorCollection(params string[] colors) => _colors = colors;
public IEnumerator GetEnumerator() => new ColorEnumerator(_colors);
}
var colors = new ColorCollection("Red", "Green", "Blue", "Yellow");
foreach (string color in colors)
Console.WriteLine(color);
// 手動枚舉
var enumerator = colors.GetEnumerator();
while (enumerator.MoveNext())
Console.WriteLine(enumerator.Current);
public class GenericColorCollection : IEnumerable
{
private readonly string[] _colors;
public GenericColorCollection(params string[] colors) => _colors = colors;
public IEnumerator GetEnumerator() => new GenericColorEnumerator(_colors);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); // 非泛型介面顯式實作
}
public class GenericColorEnumerator : IEnumerator
{
private readonly string[] _colors;
private int _position = -1;
public GenericColorEnumerator(string[] colors) => _colors = colors;
public string Current => (_position >= 0 && _position < _colors.Length) ? _colors[_position]
: throw new InvalidOperationException();
object IEnumerator.Current => Current;
public bool MoveNext() => ++_position < _colors.Length;
public void Reset() => _position = -1;
public void Dispose() { } // 無非託管資源
}
public class YieldColorCollection : IEnumerable
{
private readonly string[] _colors;
public YieldColorCollection(params string[] colors) => _colors = colors;
public IEnumerator GetEnumerator()
{
foreach (var color in _colors)
yield return color; // 編譯器自動產生狀態機類別
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
yield return 產生的枚舉器不支援 Reset (呼叫會拋出 NotSupportedException),若需支援 Reset 必須手動實作 IEnumerator。
| 特性 | 手動實作 IEnumerator | yield return |
|---|---|---|
| 程式碼量 | 多 | 極少 |
| Reset 支援 | 可控制 | 不支援 |
| 狀態管理 | 手動 | 編譯器自動產生狀態機 |
| 效能 | 略優 (無狀態機開銷) | 極佳 (編譯器優化) |
| 除錯 | 容易設中斷點 | 較難 (狀態機) |
| 適用場景 | 需精確控制、支援 Reset、教學 | 99% 一般情況 |
IEnumerable<T> (含非泛型 IEnumerable 顯式實作)IEnumerator<T> : IDisposable, IEnumeratorCurrent 正確處理邊界 (-1、超出長度)MoveNext 正確推進並回傳是否有下一項Reset 重置至初始狀態 (-1)Dispose 釋放資源 (若有)IEnumerable.GetEnumerator() → 編譯錯誤Current 未檢查邊界 → IndexOutOfRangeExceptionMoveNext 邏輯錯誤導致漏項或重複foreach 中修改集合 → InvalidOperationException (需自行處理)掌握 IEnumerable/IEnumerator 實作,是理解 C# 迭代器模式、LINQ 底層運作與自訂集合的基礎。現代開發首選 yield return,特殊需求再手動實作。