ホームページ >バックエンド開発 >C++ >C# で汎用 OrderedDictionary を実装する理由

C# で汎用 OrderedDictionary を実装する理由

Linda Hamilton
Linda Hamiltonオリジナル
2025-01-01 00:45:09756ブラウズ

Why Implement a Generic OrderedDictionary in C#?

汎用 OrderedDictionary の実装は特に難しいことではありませんが、不必要に時間がかかり、率直に言ってこのクラスは Microsoft 側の大きな見落としです。これを実装するには複数の方法がありますが、私は内部ストレージに KeyedCollection を使用することを選択しました。また、List をソートするためのさまざまなメソッドを実装することにしました。これは本質的に IList と IDictionary のハイブリッドであるためです。

インターフェイスは次のとおりです。これには、Microsoft によって提供されたこのインターフェイスの非汎用バージョンである System.Collections.Specialized.IOrderedDictionary が含まれていることに注意してください。

// https://choosealicense.com/licenses/unlicense
// または https://choosealicense.com/licenses/mit/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace mattmc3.Common.Collections.Generic {

public interface IOrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IOrderedDictionary {
    new TValue this[int index] { get; set; }
    new TValue this[TKey key] { get; set; }
    new int Count { get; }
    new ICollection<TKey> Keys { get; }
    new ICollection<TValue> Values { get; }
    new void Add(TKey key, TValue value);
    new void Clear();
    void Insert(int index, TKey key, TValue value);
    int IndexOf(TKey key);
    bool ContainsValue(TValue value);
    bool ContainsValue(TValue value, IEqualityComparer<TValue> comparer);
    new bool ContainsKey(TKey key);
    new IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();
    new bool Remove(TKey key);
    new void RemoveAt(int index);
    new bool TryGetValue(TKey key, out TValue value);
    TValue GetValue(TKey key);
    void SetValue(TKey key, TValue value);
    KeyValuePair<TKey, TValue> GetItem(int index);
    void SetItem(int index, TValue value);
}

}
ヘルパーを含む実装は次のとおりですクラス:

// http://unlicense.org
System を使用;
System.Collections.ObjectModel を使用;
System.Diagnostics を使用;
System.Collections を使用;
System.Collections.Specialized を使用;
System.Collections.Generic を使用;
を使用System.Linq;

名前空間 mattmc3.Common.Collections.Generic {

/// <summary>
/// A dictionary object that allows rapid hash lookups using keys, but also
/// maintains the key insertion order so that values can be retrieved by
/// key index.
/// </summary>
public class OrderedDictionary<TKey, TValue> : IOrderedDictionary<TKey, TValue> {

    #region Fields/Properties

    private KeyedCollection2<TKey, KeyValuePair<TKey, TValue>> _keyedCollection;

    /// <summary>
    /// Gets or sets the value associated with the specified key.
    /// </summary>
    /// <param name=&quot;key&quot;>The key associated with the value to get or set.</param>
    public TValue this[TKey key] {
        get {
            return GetValue(key);
        }
        set {
            SetValue(key, value);
        }
    }

    /// <summary>
    /// Gets or sets the value at the specified index.
    /// </summary>
    /// <param name=&quot;index&quot;>The index of the value to get or set.</param>
    public TValue this[int index] {
        get {
            return GetItem(index).Value;
        }
        set {
            SetItem(index, value);
        }
    }

    public int Count {
        get { return _keyedCollection.Count; }
    }

    public ICollection<TKey> Keys {
        get {
            return _keyedCollection.Select(x => x.Key).ToList();
        }
    }

    public ICollection<TValue> Values {
        get {
            return _keyedCollection.Select(x => x.Value).ToList();
        }
    }

    public IEqualityComparer<TKey> Comparer {
        get;
        private set;
    }

    #endregion

    #region Constructors

    public OrderedDictionary() {
        Initialize();
    }

    public OrderedDictionary(IEqualityComparer<TKey> comparer) {
        Initialize(comparer);
    }

    public OrderedDictionary(IOrderedDictionary<TKey, TValue> dictionary) {
        Initialize();
        foreach (KeyValuePair<TKey, TValue> pair in dictionary) {
            _keyedCollection.Add(pair);
        }
    }

    public OrderedDictionary(IOrderedDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) {
        Initialize(comparer);
        foreach (KeyValuePair<TKey, TValue> pair in dictionary) {
            _keyedCollection.Add(pair);
        }
    }

    #endregion

    #region Methods

    private void Initialize(IEqualityComparer<TKey> comparer = null) {
        this.Comparer = comparer;
        if (comparer != null) {
            _keyedCollection = new KeyedCollection2<TKey, KeyValuePair<TKey, TValue>>(x => x.Key, comparer);
        }
        else {
            _keyedCollection = new KeyedCollection2<TKey, KeyValuePair<TKey, TValue>>(x => x.Key);
        }
    }

    public void Add(TKey key, TValue value) {
        _keyedCollection.Add(new KeyValuePair<TKey, TValue>(key, value));
    }

    public void Clear() {
        _keyedCollection.Clear();
    }

    public void Insert(int index, TKey key, TValue value) {
        _keyedCollection.Insert(index, new KeyValuePair<TKey, TValue>(key, value));
    }

    public int IndexOf(TKey key) {
        if (_keyedCollection.Contains(key)) {
            return _keyedCollection.IndexOf(_keyedCollection[key]);
        }
        else {
            return -1;
        }
    }

    public bool ContainsValue(TValue value) {
        return this.Values.Contains(value);
    }

    public bool ContainsValue(TValue value, IEqualityComparer<TValue> comparer) {
        return this.Values.Contains(value, comparer);
    }

    public bool ContainsKey(TKey key) {
        return _keyedCollection.Contains(key);
    }

    public KeyValuePair<TKey, TValue> GetItem(int index) {
        if (index < 0 || index >= _keyedCollection.Count) {
            throw new ArgumentException(String.Format(&quot;The index was outside the bounds of the dictionary: {0}&quot;, index));
        }
        return _keyedCollection[index];
    }

    /// <summary>
    /// Sets the value at the index specified.
    /// </summary>
    /// <param name=&quot;index&quot;>The index of the value desired</param>
    /// <param name=&quot;value&quot;>The value to set</param>
    /// <exception cref=&quot;ArgumentOutOfRangeException&quot;>
    /// Thrown when the index specified does not refer to a KeyValuePair in this object
    /// </exception>
    public void SetItem(int index, TValue value) {
        if (index < 0 || index >= _keyedCollection.Count) {
            throw new ArgumentException(&quot;The index is outside the bounds of the dictionary: {0}&quot;.FormatWith(index));
        }
        var kvp = new KeyValuePair<TKey, TValue>(_keyedCollection[index].Key, value);
        _keyedCollection[index] = kvp;
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
        return _keyedCollection.GetEnumerator();
    }

    public bool Remove(TKey key) {
        return _keyedCollection.Remove(key);
    }

    public void RemoveAt(int index

以上がC# で汎用 OrderedDictionary を実装する理由の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。