GetEnumerator实现IDictionary

时间:2015-07-23 19:12:32

标签: vb.net

我正在使用LinkedHashMap作为VB.NET应用程序的池,并且我通过组合而不是继承进行扩展,因为很多字典方法都没有声明虚拟

我该如何处理:

Public NotInheritable Class LinkedDictionary(Of TKey, TValue)
    Implements IDictionary(Of TKey, TValue), 

    Private ReadOnly maxCapacity As Integer
    Private ReadOnly dictionary As New Dictionary(Of TKey, TValue)()
    Private ReadOnly queue As New Queue(Of TKey, TValue)()

    ' ...

    Public Sub Add(ByVal key As TKey, ByVal value As TValue) _
    Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Add
        dictionary.Add(key, value)
        queue.Enqueue(key)
        If queue.Count() > maxCapacity Then
            dictionary.Remove(queue.Dequeue())
        End If
    End Sub

    ' ...

    Public Function GetEnumerator() As IEnumerator(Of KeyValuePair(Of TKey, TValue)) _
    Implements IEnumerable(Of KeyValuePair(Of TKey, TValue)).GetEnumerator
        Return dictionary.GetEnumerator()
    End Function

    Public Function GetEnumerator2() As System.Collections.IEnumerator _
    Implements System.Collections.IEnumerable.GetEnumerator
         Return dictionary.GetEnumerator() 
         ' ??? there's only one GetEnumerator Method in Dictionary(Of TKey, TValue)
    End Function

End Class

常规字典类如何处理此实现?

1 个答案:

答案 0 :(得分:3)

如果您想查看.NET框架中的某些内容是如何实现的,您只需查看Reference Source即可。例如,这是code for the Dictionary class。如果您要查找的代码未托管在Reference Source上,您还可以使用众多.NET反编译器之一来查看任何.NET Framework库的源代码(例如免费的{{3} })。

更具体地回答您的问题,正如参考资料显示的那样,GetEnumerator类中Dictionary方法的实现如下:

public Enumerator GetEnumerator() {
    return new Enumerator(this, Enumerator.KeyValuePair);
}

IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() {
    return new Enumerator(this, Enumerator.KeyValuePair);
}

前者是IDictionary.GetEnumerator的实现,后者是IDictionary(Of TKey, TValue).GetEnumerator的实现。所以它所做的就是创建一个新的Enumerator类(它是在Dictionary类中声明的嵌套类),将自己作为源字典参数。

它有点长,但这是嵌套Enumerator类的代码:

[Serializable]
public struct Enumerator: IEnumerator<KeyValuePair<TKey,TValue>>,
        IDictionaryEnumerator
    {
        private Dictionary<TKey,TValue> dictionary;
        private int version;
        private int index;
        private KeyValuePair<TKey,TValue> current;
        private int getEnumeratorRetType;  // What should Enumerator.Current return?

        internal const int DictEntry = 1;
        internal const int KeyValuePair = 2;

        internal Enumerator(Dictionary<TKey,TValue> dictionary, int getEnumeratorRetType) {
            this.dictionary = dictionary;
            version = dictionary.version;
            index = 0;
            this.getEnumeratorRetType = getEnumeratorRetType;
            current = new KeyValuePair<TKey, TValue>();
        }

        public bool MoveNext() {
            if (version != dictionary.version) {
                ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
            }

            // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
            // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
            while ((uint)index < (uint)dictionary.count) {
                if (dictionary.entries[index].hashCode >= 0) {
                    current = new KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value);
                    index++;
                    return true;
                }
                index++;
            }

            index = dictionary.count + 1;
            current = new KeyValuePair<TKey, TValue>();
            return false;
        }

        public KeyValuePair<TKey,TValue> Current {
            get { return current; }
        }

        public void Dispose() {
        }

        object IEnumerator.Current {
            get { 
                if( index == 0 || (index == dictionary.count + 1)) {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
                }      

                if (getEnumeratorRetType == DictEntry) {
                    return new System.Collections.DictionaryEntry(current.Key, current.Value);
                } else {
                    return new KeyValuePair<TKey, TValue>(current.Key, current.Value);
                }
            }
        }

        void IEnumerator.Reset() {
            if (version != dictionary.version) {
                ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
            }

            index = 0;
            current = new KeyValuePair<TKey, TValue>();    
        }

        DictionaryEntry IDictionaryEnumerator.Entry {
            get { 
                if( index == 0 || (index == dictionary.count + 1)) {
                     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
                }                        

                return new DictionaryEntry(current.Key, current.Value); 
            }
        }

        object IDictionaryEnumerator.Key {
            get { 
                if( index == 0 || (index == dictionary.count + 1)) {
                     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
                }                        

                return current.Key; 
            }
        }

        object IDictionaryEnumerator.Value {
            get { 
                if( index == 0 || (index == dictionary.count + 1)) {
                     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
                }                        

                return current.Value; 
            }
        }
    }

正如您所看到的,由于Enumerator类嵌套在Dictionary类中,因此它可以访问并使用某些字典的私有成员,例如{{1}和version您通常无法从外部访问。