IDictionaryEnumerator 接口
定义
C#
public interface IDictionaryEnumerator : System.Collections.IEnumerator
- 派生
-
- 实现
-
示例
此代码示例演示如何定义实现接口的 IDictionaryEnumerator 字典枚举器。
C#
using System;
using System.Collections;
// This class implements a simple dictionary using an array of DictionaryEntry objects (key/value pairs).
public class SimpleDictionary : IDictionary
{
// The array of items
private DictionaryEntry[] items;
private Int32 ItemsInUse = 0;
// Construct the SimpleDictionary with the desired number of items.
// The number of items cannot change for the life time of this SimpleDictionary.
public SimpleDictionary(Int32 numItems)
{
items = new DictionaryEntry[numItems];
}
#region IDictionary Members
public bool IsReadOnly { get { return false; } }
public bool Contains(object key)
{
Int32 index;
return TryGetIndexOfKey(key, out index);
}
public bool IsFixedSize { get { return false; } }
public void Remove(object key)
{
if (key == null) throw new ArgumentNullException("key");
// Try to find the key in the DictionaryEntry array
Int32 index;
if (TryGetIndexOfKey(key, out index))
{
// If the key is found, slide all the items up.
Array.Copy(items, index + 1, items, index, ItemsInUse - index - 1);
ItemsInUse--;
}
else
{
// If the key is not in the dictionary, just return.
}
}
public void Clear() { ItemsInUse = 0; }
public void Add(object key, object value)
{
// Add the new key/value pair even if this key already exists in the dictionary.
if (ItemsInUse == items.Length)
throw new InvalidOperationException("The dictionary cannot hold any more items.");
items[ItemsInUse++] = new DictionaryEntry(key, value);
}
public ICollection Keys
{
get
{
// Return an array where each item is a key.
Object[] keys = new Object[ItemsInUse];
for (Int32 n = 0; n < ItemsInUse; n++)
keys[n] = items[n].Key;
return keys;
}
}
public ICollection Values
{
get
{
// Return an array where each item is a value.
Object[] values = new Object[ItemsInUse];
for (Int32 n = 0; n < ItemsInUse; n++)
values[n] = items[n].Value;
return values;
}
}
public object this[object key]
{
get
{
// If this key is in the dictionary, return its value.
Int32 index;
if (TryGetIndexOfKey(key, out index))
{
// The key was found; return its value.
return items[index].Value;
}
else
{
// The key was not found; return null.
return null;
}
}
set
{
// If this key is in the dictionary, change its value.
Int32 index;
if (TryGetIndexOfKey(key, out index))
{
// The key was found; change its value.
items[index].Value = value;
}
else
{
// This key is not in the dictionary; add this key/value pair.
Add(key, value);
}
}
}
private Boolean TryGetIndexOfKey(Object key, out Int32 index)
{
for (index = 0; index < ItemsInUse; index++)
{
// If the key is found, return true (the index is also returned).
if (items[index].Key.Equals(key)) return true;
}
// Key not found, return false (index should be ignored by the caller).
return false;
}
private class SimpleDictionaryEnumerator : IDictionaryEnumerator
{
// A copy of the SimpleDictionary object's key/value pairs.
DictionaryEntry[] items;
Int32 index = -1;
public SimpleDictionaryEnumerator(SimpleDictionary sd)
{
// Make a copy of the dictionary entries currently in the SimpleDictionary object.
items = new DictionaryEntry[sd.Count];
Array.Copy(sd.items, 0, items, 0, sd.Count);
}
// Return the current item.
public Object Current { get { ValidateIndex(); return items[index]; } }
// Return the current dictionary entry.
public DictionaryEntry Entry
{
get { return (DictionaryEntry) Current; }
}
// Return the key of the current item.
public Object Key { get { ValidateIndex(); return items[index].Key; } }
// Return the value of the current item.
public Object Value { get { ValidateIndex(); return items[index].Value; } }
// Advance to the next item.
public Boolean MoveNext()
{
if (index < items.Length - 1) { index++; return true; }
return false;
}
// Validate the enumeration index and throw an exception if the index is out of range.
private void ValidateIndex()
{
if (index < 0 || index >= items.Length)
throw new InvalidOperationException("Enumerator is before or after the collection.");
}
// Reset the index to restart the enumeration.
public void Reset()
{
index = -1;
}
}
public IDictionaryEnumerator GetEnumerator()
{
// Construct and return an enumerator.
return new SimpleDictionaryEnumerator(this);
}
#endregion
#region ICollection Members
public bool IsSynchronized { get { return false; } }
public object SyncRoot { get { throw new NotImplementedException(); } }
public int Count { get { return ItemsInUse; } }
public void CopyTo(Array array, int index) { throw new NotImplementedException(); }
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
// Construct and return an enumerator.
return ((IDictionary)this).GetEnumerator();
}
#endregion
}
public sealed class App
{
static void Main()
{
// Create a dictionary that contains no more than three entries.
IDictionary d = new SimpleDictionary(3);
// Add three people and their ages to the dictionary.
d.Add("Jeff", 40);
d.Add("Kristin", 34);
d.Add("Aidan", 1);
Console.WriteLine("Number of elements in dictionary = {0}", d.Count);
Console.WriteLine("Does dictionary contain 'Jeff'? {0}", d.Contains("Jeff"));
Console.WriteLine("Jeff's age is {0}", d["Jeff"]);
// Display every entry's key and value.
foreach (DictionaryEntry de in d)
{
Console.WriteLine("{0} is {1} years old.", de.Key, de.Value);
}
// Remove an entry that exists.
d.Remove("Jeff");
// Remove an entry that does not exist, but do not throw an exception.
d.Remove("Max");
// Show the names (keys) of the people in the dictionary.
foreach (String s in d.Keys)
Console.WriteLine(s);
// Show the ages (values) of the people in the dictionary.
foreach (Int32 age in d.Values)
Console.WriteLine(age);
}
}
// This code produces the following output.
//
// Number of elements in dictionary = 3
// Does dictionary contain 'Jeff'? True
// Jeff's age is 40
// Jeff is 40 years old.
// Kristin is 34 years old.
// Aidan is 1 years old.
// Kristin
// Aidan
// 34
// 1
注解
C# 语言的 foreach 语句(在 Visual Basic 中为 for each )隐藏了枚举数的复杂性。 因此,建议使用 foreach ,而不是直接操作枚举器。
枚举器可用于读取集合中的数据,但不能用于修改基础集合。
最初,枚举数定位在集合中第一个元素的前面。 该方法 Reset 还会将枚举器带回此位置。 在此位置上,未定义 Current。 因此,在读取值Current之前,必须调用MoveNext该方法以将枚举器提升到集合的第一个元素。
在调用 Current 或 MoveNext 之前,Reset 返回同一对象。 MoveNext 将 Current 设置为下一个元素。
如果 MoveNext 传递集合的末尾,枚举器将定位在集合中的最后一个元素之后并 MoveNext 返回 false 。 当枚举器处于此位置时,后续调用 MoveNext 也会返回 false 。 如果返回false 的最后一次调用MoveNext,Current则为未定义。 若要再次将 Current 设置为集合的第一个元素,可以调用 Reset 并接着调用 MoveNext。
只要集合保持不变,枚举器就仍有效。 如果对集合进行了更改,例如添加、修改或删除元素,枚举器将不可恢复地失效,并且下次调用 MoveNext 或 Reset 引发枚举 InvalidOperationException器。
枚举数没有对集合的独占访问权;因此,从头到尾对一个集合进行枚举在本质上不是一个线程安全的过程。 即使某个集合已同步,其他线程仍可以修改该集合,这会导致枚举数引发异常。 若要确保枚举过程中的线程安全性,可以在整个枚举期间锁定集合,或者捕获由其他线程进行的更改所导致的异常。
实施者说明
继承IEnumerator自的属性Current返回Object一个装箱DictionaryEntry的属性。 它类似于属性 Entry ,只不过 Entry 返回一个 DictionaryEntry 而不是一个 Object。
属性
方法
适用于
产品 |
版本 |
.NET |
Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7 |
.NET Framework |
1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8 |
.NET Standard |
1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1 |
UWP |
10.0 |
Xamarin.iOS |
10.8 |
Xamarin.Mac |
3.0 |
另请参阅
|