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

構建可反轉排序的泛型字典 (5/9):實現 IEnumerable<KeyValuePair> 與雙介面枚舉器

     編輯:關於C#

介面繼承關係圖解

`ReversibleSortedList` 實現 6 個介面:

IDictionary → ICollection> → IEnumerable>
IDictionary              → ICollection                → IEnumerable

本質上只需實現左側兩個核心介面,右側自動滿足。首要任務:實現最底層的 `IEnumerable` / `IEnumerable>`。

枚舉器設計:結構體實現雙介面

為了同時支援泛型 `IEnumerator>` 與非泛型 `IDictionaryEnumerator`(供 `DictionaryEntry` 使用),定義結構體 `Enumerator`:


private struct Enumerator : 
    IEnumerator>, 
    IDictionaryEnumerator, 
    IEnumerator, 
    IDisposable
{
    private readonly ReversibleSortedList _dict;
    private int _index, _version;
    private K _key; private V _value;

    internal Enumerator(ReversibleSortedList dict)
    {
        _dict = dict; _version = dict._version; _index = 0;
        _key = default; _value = default;
    }

    public void Dispose() { _index = 0; _key = default; _value = default; }

    // 版本檢查核心
    private void CheckVersion()
    {
        if (_version != _dict._version)
            throw new InvalidOperationException("枚舉版本檢查失敗:集合在枚舉過程中被修改");
    }

    public bool MoveNext()
    {
        CheckVersion();
        if (_index < _dict.Count)
        {
            _key = _dict._keys[_index];
            _value = _dict._values[_index];
            _index++;
            return true;
        }
        _index = _dict.Count + 1;
        _key = default; _value = default;
        return false;
    }

    // IEnumerator 當前元素
    public KeyValuePair Current => new KeyValuePair(_key, _value);

    // IDictionaryEnumerator 成員
    public DictionaryEntry Entry => new DictionaryEntry(_key, _value);
    object IDictionaryEnumerator.Key => GetKeyOrThrow();
    object IDictionaryEnumerator.Value => GetValueOrThrow();

    // 非泛型 IEnumerator.Current 返回 DictionaryEntry 以相容舊代碼
    object IEnumerator.Current => Entry;

    void IEnumerator.Reset()
    {
        CheckVersion();
        _index = 0; _key = default; _value = default;
    }

    private K GetKeyOrThrow()
    {
        if (_index == 0 || _index == _dict.Count + 1)
            throw new InvalidOperationException("枚舉器未定位於有效元素");
        return _key;
    }
    private V GetValueOrThrow() { /* 同理 */ return _value; }
}

版本號機制

  • 類別欄位 `private int _version`,每次修改結構(Add/Insert/Remove/Clear/Reverse)時 `_version++`。
  • 枚舉器構造時捕獲 `_version` 快照。
  • `MoveNext`/`Reset` 時比對,不一致拋出 `InvalidOperationException`。
  • 此模式源自 .NET Framework `List`、`Dictionary` 等標準集合。

介面實現:GetEnumerator 方法


// 類別宣告加上介面
public class ReversibleSortedList : 
    IEnumerable>, 
    IEnumerable
{
    // 顯式實現泛型版本
    IEnumerator> IEnumerable>.GetEnumerator()
        => new Enumerator(this);

    // 顯式實現非泛型版本
    IEnumerator IEnumerable.GetEnumerator()
        => new Enumerator(this);
}

測試驗證


static void Main()
{
    var rs = new ReversibleSortedList();
    rs.Add(3, "a"); rs.Add(1, "b"); rs.Add(2, "c");
    rs.Add(6, "d"); rs.Add(5, "e"); rs.Add(4, "f");

    Console.WriteLine("泛型 foreach (KeyValuePair):");
    foreach (var kv in rs) Console.WriteLine($"{kv.Key} -> {kv.Value}");

    // 驗證版本檢查
    Console.WriteLine("\n測試枚舉中修改集合:");
    try
    {
        foreach (var kv in rs)
        {
            if (kv.Key == 3) rs.Add(99, "x"); // 觸發版本變更
        }
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine($"預期異常: {ex.Message}");
    }
}

遺憾與下一步

雖然 `Enumerator` 實現了 `IDictionaryEnumerator`,但**只有實現 `IDictionary` 介面並由其 `GetEnumerator()` 返回該枚舉器**,`foreach (DictionaryEntry de in (IDictionary)dict)` 才能工作。下一篇將實現非泛型 `IDictionary` 介面。

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