Frage

Meine Klasse enthält einen Dictionary<T, S> dict, und ich mag eine ReadOnlyCollection<T> des Schlüssels belichten. Wie kann ich dies tun, ohne den Dictionary<T, S>.KeyCollection dict.Keys auf ein Array zu kopieren und dann als ReadOnlyCollection das Array aussetzt?

Ich möchte die ReadOnlyCollection eine richtige Wrapper sein, dh. um Änderungen in dem zugrunde liegenden Wörterbuch, und als ich ihm das Kopieren die Sammlung zu einem Array verstehen wird dies nicht tun (wie auch scheinbar ineffizient - ich weiß nicht wirklich eine neue Kollektion will, nur die zugrunde liegende Sammlung von Schlüsseln zu belichten .. .). Irgendwelche Ideen wäre sehr geschätzt!

Edit: Ich bin mit C # 2.0, also keine Erweiterungsmethoden wie .ToList (leicht) zur Verfügung haben.

War es hilfreich?

Lösung

Wenn Sie wirklich verwenden Readonlycollection wollen , das Problem ist, dass der Konstruktor von Readonlycollection nimmt eine IList , während die KeyCollection des Wörterbuchs ist nur ein ICollection .

Wenn Sie also das KeyCollection in einem Readonlycollection wickeln möchten, müssen Sie einen Adapter (oder Wrapper) Typ, Implementierung IList , das Einwickeln der KeyCollection haben zu erstellen. So würde es wie folgt aussehen:

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

wenn auch nicht sehr elegant, zumal die KeyCollection bereits eine Nur-Lese-Sammlung, und dass Sie es einfach um, als eine ICollection passieren könnten :)

Andere Tipps

DrJokepu sagte, dass es schwierig sein könnte, einen Wrapper für Keys Sammlung zu implementieren. Aber in diesem speziellen Fall, ich denke, die Umsetzung nicht so schwierig ist, weil, wie wir wissen, ist dies ein Nur-Lese-Wrapper ist.

Dies ermöglicht es uns, einige Methoden zu ignorieren, die, in anderen Fällen wären schwer zu implementieren.

Hier ist eine schnelle Umsetzung der Wrapper für 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
}

Dies ist vielleicht nicht die beste Implementierung für diese Methoden sein :) aber es war einfach zu beweisen, dass dies geschehen könnte.

Angenommen, Sie sind mit C # 3.0 und Sie haben:

Dictionary d;

Dann

Readonlycollection r = new Readonlycollection (d.Keys.ToList ());

Sie werden auch die System.Linq Namespace zu importieren.

Leider kann man nicht an, dass direcly soweit ich weiß, wie KeyCollection<T> der nichts aussetzen, dass Sie dies leicht zu tun erlauben würde.

Sie könnten, aber Unterklasse ReadOnlyCollection<T>, so dass sein Konstruktor empfängt das Wörterbuch selbst und die entsprechenden Methoden außer Kraft setzen, so dass es die Dictionary Artikel aussetzt, als ob sie ihre eigenen Produkte waren.

Für die Aufzeichnung in .NET 4.6 implementiert die KeyCollection<T> IReadOnlyCollection<T>, also wenn Sie diese Schnittstelle verwenden, können Sie noch Änderungen an dem Wörterbuch reflektieren, noch O erhalten (1) enthält, und da die Schnittstelle covariant ist, können Sie Rückkehr IReadOnlyCollection<some base type>

Es ist hässlich, aber das wird es tun

Dictionary<int,string> dict = new Dictionary<int, string>();
...
ReadOnlyCollection<int> roc = new ReadOnlyCollection<int>((new List<int>((IEnumerable<int>)dict.Keys)));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top