7

私のクラスには が含まれており、キーのDictionary<T, S> dictを公開したいと考えてReadOnlyCollection<T>います。Dictionary<T, S>.KeyCollection dict.Keysを配列にコピーしてから、配列を として公開せずにこれを行うにはどうすればよいReadOnlyCollectionですか?

ReadOnlyCollectionを適切なラッパーにしたい 、つまり. 基礎となるディクショナリの変更を反映します。私が理解しているように、コレクションを配列にコピーしてもこれは行われません(非効率的に見えるだけでなく、実際には新しいコレクションは必要ありません。基礎となるキーのコレクションを公開するためだけです.. .)。どんなアイデアでも大歓迎です!

編集: 私は C# 2.0 を使用しているため、.ToList (簡単に) などの拡張メソッドは使用できません。

4

6 に答える 6

5

本当に ReadOnlyCollection<T> を使用したい場合、問題は、ReadOnlyCollection<T> のコンストラクターが IList<T> を受け取るのに対し、Dictionary の KeyCollection は ICollection<T> のみであるということです。

そのため、KeyCollection を ReadOnlyCollection にラップする場合は、アダプター (またはラッパー) 型を作成し、IList<T> を実装して KeyCollection をラップする必要があります。したがって、次のようになります。

var dictionary = ...;
var readonly_keys = new ReadOnlyCollection<T> (new CollectionListWrapper<T> (dictionary.Keys)
);

ただし、特に KeyCollection はすでに読み取り専用のコレクションであり、 ICollection<T> として単純に渡すことができるため、あまりエレガントではありません:)

于 2008-11-12T14:39:03.457 に答える
5

DrJokepu 氏は、Keys Collection のラッパーを実装するのは難しいかもしれないと述べました。しかし、この特定のケースでは、ご存じのとおり、これは読み取り専用のラッパーであるため、実装はそれほど難しくないと思います。

これにより、他の場合には実装が難しいいくつかのメソッドを無視することができます。

Dictionary.KeyCollection のラッパーの簡単な実装を次に示します。

class MyListWrapper<T, TValue> : IList<T>
{
    private Dictionary<T, TValue>.KeyCollection keys;

    public MyListWrapper(Dictionary<T, TValue>.KeyCollection keys)
    {
        this.keys = keys;
    }

    #region IList<T> Members

    public int IndexOf(T item)
    {
        if (item == null)
            throw new ArgumentNullException();
        IEnumerator<T> e = keys.GetEnumerator();
        int i = 0;
        while (e.MoveNext())
        {
            if (e.Current.Equals(item))
                return i;
            i++;
        }
        throw new Exception("Item not found!");
    }

    public void Insert(int index, T item)
    {
        throw new NotImplementedException();
    }

    public void RemoveAt(int index)
    {
        throw new NotImplementedException();
    }

    public T this[int index]
    {
        get
        {
            IEnumerator<T> e = keys.GetEnumerator();
            if (index < 0 || index > keys.Count)
                throw new IndexOutOfRangeException();
            int i = 0;
            while (e.MoveNext() && i != index)
            {
                i++;
            }
            return e.Current;
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    #endregion

    #region ICollection<T> Members

    public void Add(T item)
    {
        throw new NotImplementedException();
    }

    public void Clear()
    {
        throw new NotImplementedException();
    }

    public bool Contains(T item)
    {
        return keys.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        keys.CopyTo(array, arrayIndex);
    }

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

    public bool IsReadOnly
    {
        get { return true; }
    }

    public bool Remove(T item)
    {
        throw new NotImplementedException();
    }

    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
        return keys.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return keys.GetEnumerator();
    }

    #endregion
}

これは、これらのメソッドの最適な実装ではないかもしれません :) が、これが実行できることを証明するためだけのものでした。

于 2008-11-12T16:25:21.603 に答える
1

C# 3.0 を使用していて、次のものがあると仮定します。

Dictionary< T,S > d;

それで

ReadOnlyCollection< T > r = new ReadOnlyCollection< T >( d.Keys.ToList() );

System.Linq 名前空間もインポートする必要があります。

于 2008-11-12T14:48:45.667 に答える
1

残念ながら、私が知る限り、KeyCollection<T>これを簡単に行うことができるものは何も公開されていないため、直接それを行うことはできません.

ただし、コンストラクターがディクショナリ自体を受け取るようにサブクラスReadOnlyCollection<T>化し、適切なメソッドをオーバーライドして、ディクショナリの項目を独自の項目であるかのように公開することができます。

于 2008-11-12T15:04:05.123 に答える
0

めんどくさいけどこれでいける

Dictionary<int,string> dict = new Dictionary<int, string>();
...
ReadOnlyCollection<int> roc = new ReadOnlyCollection<int>((new List<int>((IEnumerable<int>)dict.Keys)));
于 2008-11-12T14:45:47.967 に答える