首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 泛型集合介面 IEnumerable<T> 與 IEnumerator<T> 實作詳解

     編輯:關於C語言

介面體系架構


IEnumerable → GetEnumerator() → IEnumerator
    │                              ├── Current (T)
    │                              ├── MoveNext() (bool)
    │                              └── Dispose()
    └── IEnumerable (非泛型) 為相容性保留

自訂集合實作範例:ListBoxTest


public class ListBoxTest : IEnumerable
{
    private string[] _strings;
    private int _count;

    public ListBoxTest(string str1, string str2)
    {
        _strings = new string[8];
        _strings[0] = str1;
        _strings[1] = str2;
        _count = 2;
    }

    public void Add(string s)
    {
        if (_count < _strings.Length)
            _strings[_count++] = s;
    }

    // 泛型介面實作
    public IEnumerator GetEnumerator()
    {
        for (int i = 0; i < _count; i++)
            yield return _strings[i]; // 編譯器自動生成狀態機
    }

    // 非泛型介面顯式實作
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

foreach 編譯器降級原理


// 原始碼
foreach (string s in listBox)
    Console.WriteLine(s);

// 降級後 (簡化)
var enumerator = listBox.GetEnumerator();
try
{
    while (enumerator.MoveNext())
    {
        string s = enumerator.Current;
        Console.WriteLine(s);
    }
}
finally
{
    (enumerator as IDisposable)?.Dispose();
}

yield return 狀態機優勢

  • 延遲執行:逐個產生元素,記憶體效率高
  • 狀態保持:自動維護迴圈變數、位置
  • 程式碼簡潔:無需手寫 IEnumerator 類別

手寫 IEnumerator 類別(教學用)


public class ListBoxEnumerator : IEnumerator
{
    private readonly ListBoxTest _collection;
    private int _index = -1;

    public ListBoxEnumerator(ListBoxTest collection) => _collection = collection;

    public string Current => _index >= 0 && _index < _collection.Count 
        ? _collection[_index] 
        : throw new InvalidOperationException();

    object IEnumerator.Current => Current;

    public bool MoveNext() => ++_index < _collection.Count;

    public void Reset() => _index = -1;

    public void Dispose() { }
}

最佳實踐清單

  1. 集合類別**必須**實作 IEnumerable<T>
  2. 優先使用 yield return 而非手寫列舉器
  3. 顯式實作非泛型 IEnumerable.GetEnumerator() 避免命名衝突
  4. Current 在 MoveNext() 返回 false 前不可存取
  5. 實作 IDisposable 釋放非託管資源(檔案、資料庫連線等)

進階:唯讀集合介面


// .NET 4.5+ 建議暴露
public IReadOnlyList Items => _list.AsReadOnly();
// 或
public IReadOnlyCollection Items => _list;

防止呼叫端修改內部集合,語意更清晰。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved