문제

내 수업에는 a가 포함되어 있습니다 Dictionary<T, S> dict, 그리고 나는 노출하고 싶습니다 ReadOnlyCollection<T> 열쇠의. 복사하지 않고 어떻게 할 수 있습니까? Dictionary<T, S>.KeyCollection dict.Keys 배열로 배열을 ReadOnlyCollection?

나는 원한다 ReadOnlyCollection 적절한 포장지가 되려면, 즉. 기본 사전의 변화를 반영하기 위해, 내가 이해하기 위해, 컬렉션을 배열에 복사하는 것은 이것을 수행하지 않을 것입니다 (비효율적 인 것처럼 보입니다. 실제로 새로운 컬렉션을 원하지 않습니다. 단지 기본 키 모음을 노출시키기 위해 .. .). 어떤 아이디어라도 대단히 감사 할 것입니다!

편집 : C# 2.0을 사용하고 있으므로 .tolist (쉽게)와 같은 확장 방법이 없습니다.

도움이 되었습니까?

해결책

정말로 readonlycollection을 사용하고 싶다면u003CT> , 문제는 readonlycollection의 생성자입니다u003CT> Ilist를 취합니다u003CT> , 사전의 키 수집은 단지 iCollection 일뿐입니다.u003CT> .

따라서 readOnlyCollection으로 키 컬렉션을 래핑하려면 어댑터 (또는 래퍼) 유형을 만들어 ILIST 구현해야합니다.u003CT> 키 수집을 감싸십시오. 그래서 그것은 다음과 같습니다.

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

특히 키 수집이 이미 Readonly Collection이기 때문에 매우 우아하지는 않습니다.u003CT> :)

다른 팁

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
}

이것은 이러한 방법에 가장 적합한 구현이 아닐 수도 있습니다 :) 그러나 이것이 이루어질 수 있음을 증명하기위한 것이 었습니다.

C# 3.0을 사용하고 있다고 가정하고 다음과 같이 가정합니다.

사전 <t, s> d;

그 다음에

readOnlyCollection <T> r = 새로운 readOnlyCollection <T> (d.keys.tolist ());

또한 System.linq 네임 스페이스를 가져와야합니다.

불행히도 당신은 내가 아는 한 그에게 그다지 말할 수 없습니다. KeyCollection<T> 쉽게 할 수있는 어떤 것도 노출하지 않습니다.

그러나 서브 클래스가 될 수 있습니다 ReadOnlyCollection<T> 따라서 생성자는 사전 자체를 수신하고 적절한 방법을 무시하여 사전의 항목이 마치 자체 항목 인 것처럼 노출되도록합니다.

레코드의 경우 .NET 4.6에서 KeyCollection<T> 구현 IReadOnlyCollection<T>, 해당 인터페이스를 사용하는 경우, 사전에 대한 변경 사항을 여전히 반영 할 수 있고, 여전히 O (1)가 포함되며 인터페이스가 공분산이므로 반환 할 수 있습니다. IReadOnlyCollection<some base type>

못 생겼지 만 이것은 할 것입니다

Dictionary<int,string> dict = new Dictionary<int, string>();
...
ReadOnlyCollection<int> roc = new ReadOnlyCollection<int>((new List<int>((IEnumerable<int>)dict.Keys)));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top