Если вы хотите узнать, как реализовано что-то в .NET Framework, вы можете просто взглянуть на Reference Source. Например, вот code for the Dictionary class. Если код, который вы ищете, не размещен в Reference Source, вы также можете использовать один из многих декомпиляторов .NET, чтобы взглянуть на источник любой из библиотек .NET Framework (например, бесплатный ILSpy).
Чтобы ответить на ваш вопрос более конкретно, как показывает источник задания, реализация метода 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
класса, он имеет доступ к, и делает использование некоторых из частных членов словаря, таких как version
и entries
, к которым вы обычно не имеете доступа извне.
Отличный ресурс! Я думаю, что кое-что немного запутывает здесь, как реализуются реализации интерфейса VB.NET ... 'public Enumerator GetEnumerator()' в C# - это открытый метод, который обрабатывается GetEnumerator. У них также есть другая подпись: 'IEnumerator> IEnumerable >. GetEnumerator()', который является тем, который обрабатывает интерфейс IEnumerable. Это будет 'private GetEnumerator() обрабатывает IEnumerable (Of KeyValuePair (Of TKey, TValue)). GetEnumerator' в VB.NET, но это можно назвать только в том случае, если ссылка является« IEnumerable (Of [Type]) ». –
Ах. Правильно. Я пропустил это. Поскольку он реализует как «IDictionary», так и «IDictionary (Of TKey, TValue)», он фактически реализует метод «GetEnumerator» дважды (один раз для каждого интерфейса). Я обновил свой ответ, чтобы отразить это. Спасибо что подметил это. На стороне примечание, в основном, я предпочитаю C# для VB.NET, но синтаксис реализации интерфейса - одна из тех немногих вещей, которые, на мой взгляд, лучше в VB.NET. Мне нравится более явный синтаксис в VB.NET, когда он говорит, какой метод реализует что. –
Я на той же странице! VB.NET просто так многословен. –