using System;
using System.Collections;class Example
{
    public static void Main()
    {
        // Create a new hash table.
        //
        Hashtable openWith = new Hashtable();        // Add some elements to the hash table. There are no 
        // duplicate keys, but some of the values are duplicates.
        openWith.Add("txt", "notepad.exe");
        openWith.Add("bmp", "paint.exe");
        openWith.Add("dib", "paint.exe");
        openWith.Add("rtf", "wordpad.exe");        // When you use foreach to enumerate hash table elements,
        // the elements are retrieved as KeyValuePair objects.
        Console.WriteLine();
        foreach (DictionaryEntry de in openWith)
        {
            Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
        }
    }
}
以上为MSDN范例,里面使用foreach (DictionaryEntry de in openWith)遍历了Hashtable的内容,但怎么看出Hashtable对象是DictionaryEntry类构成的呢,从对象浏览器内只能查到Hashtable支持public virtual System.Collections.IDictionaryEnumerator GetEnumerator(),从IDictionaryEnumerator得到一个DictionaryEntry类对象阿,这怎么来理解呢

解决方案 »

  1.   

    msdn上写的IDictionary 接口是键/值对的非通用集合的基接口。有关该接口的泛型版本的信息,请参见 System.Collections.Generic.IDictionary。每个元素都是一个存储在 DictionaryEntry 对象中的键/值对。每一对都必须有唯一的键。实现在是否允许键为 空引用(在 Visual Basic 中为 Nothing) 方面有所不同。此值可以为 空引用(在 Visual Basic 中为 Nothing),并且不必是唯一的。IDictionary 接口允许对所包含的键和值进行枚举,但这并不意味着任何特定的排序顺序。IDictionary 实现有三种类别:只读、固定大小、可变大小。无法修改只读 IDictionary 对象。固定大小的 IDictionary 对象不允许添加或移除元素,但允许修改现有元素。可变大小的 IDictionary 对象允许添加、移除和修改元素。C# 语言中的 foreach 语句(在 Visual Basic 中为 for each)需要集合中每个元素的类型。由于 IDictionary 对象的每个元素都是一个键/值对,因此元素类型既不是键的类型,也不是值的类型。而是 DictionaryEntry 类型。例如: 
    foreach (DictionaryEntry myDE in myHashtable) {...}
     foreach 语句是对枚举数的包装,它只允许从集合中读取,不允许写入集合。给实现者的说明 实现类必须有一种方式来对键进行比较。 
      

  2.   

    凡是能用 foreach遍历的 都是 实现了 IEnumerable 借口的..
    反之则不能用foreach遍历
      

  3.   


    这个我也看到了,
    C# 语言中的 foreach 语句(在 Visual Basic 中为 for each)需要集合中每个元素的类型。由于 Hashtable 的每个元素都是一个键/值对,因此元素类型既不是键的类型,也不是值的类型。而是 DictionaryEntry 类型。
    但是,我不能理解的是,对一般的数组,我们知道如果是string数组,那么它每一个单元都是string变量,但hashtable,在它的类定义里却没有明确的说明。是不是所有的key/value都是DictionaryEntry 类型呢?
      

  4.   

    而且为什么直接写
    IDictionaryEnumerator myIDE = myHashtable.GetEnumerator();
    System.Collections.DictionaryEntry obj = myIDE.Entry;
    这样的代码就会提示异常呢未处理 System.InvalidOperationException
      Message="枚举或者尚未开始或者已经结束。"
      Source="mscorlib"
      StackTrace:
           在 System.Collections.Hashtable.HashtableEnumerator.get_Entry()
           在 Using_IEnumerator.Main() 位置 d:\work\Visual Studio 2005\Projects\test10\test10\Program.cs:行号 26
           在 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
           在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           在 System.Threading.ThreadHelper.ThreadStart()
      

  5.   

    DictionaryEntry结构就是key/value对IEnumerable是枚举接口,要这样用 Hashtable myHashtable = new Hashtable();
            IDictionaryEnumerator myIDE = myHashtable.GetEnumerator();
            while (myIDE.MoveNext())
            {
                System.Collections.DictionaryEntry obj = myIDE.Entry; 
            }或者用foreach遍历
      

  6.   


    IDictionaryEnumerator myIDE = myHashtable.GetEnumerator(); 
    这里的myIDE只是获取得了一个迭代器引用,初始状态并未指向任何Entry,类似于数组的索引值为-1的时候,所以这里直接取myIDE.Entry会报错。只有当执行了myIDE.MoveNext(),且返回的值为true的时候,myIDE.Entry才会真正指向集合里的某个Entry的。当返回值为false的时候表示迭代完成,这里myIDE.Entry又是未指向任务Entry状态,类似于数组索引值等于Array.Count(索引从0开始),要想再次使用迭代器的话,调用Reset方法,这时相当于数组的索引设置为-1的状态。
      

  7.   

    凡是实事了IEnumerable接口的都可以用在foreach中,但不一定都是DirectoryEntry,典型的是MS自己的Dictionary类就是使用的KeyValuePair,foreach中迭代的类型其实是根据IEnumerable的实现类的实例返回的IEnumerator接口的Current属性的具体类型来决定的,这个具体类型在实现IEnumerator接口的时候就定义好了的。
    这里的foreach只是一个简化跌代器的操作,但不限于显示声明的迭代器,使用yield关键字声明的同样可以用foreach迭代