C# HashTable 雜湊表 & DictionaryEntry  & foreach

  • 11970
  • 0
  • C#
  • 2019-03-20

雜湊表 (HashTable) 主要是處理類似key/value的鍵值,一個key 對應 一個value 。

Hashtable中key/value鍵值對均為object類型,所以Hashtable可以支援任何類型的key/value鍵值對.

此外,在遍歷hashTable時,我們使用了DictionaryEntry  以及 foreach ,卻碰到了問題。

HashTable 雜湊表

簡易來說,hashTable如同一個表單。例如一個班級有男有女,通常我們會整理一個表如下:

key value(人)
24
25

這時候若我們要問說請問這個班級男生有幾人時,我們應該就會到這張表查詢 男  也就是 我們的key

常用的簡單操作

1.添加key / value  :  HashtableObject.Add(key,value);

2.移除某一個key :  HashtableObject.remove(key);

3.移除整個talbe : HashtableObject.Clear();

4.hastTable中是否含有此key : HashtableObject.Contains(key)


code呈現

如果我的hashTable 裡面有資料了 那我該怎麼抓取所有在裡面的資料呢??

這時候就需要 DictionaryEntry  以及 foreach  來遍歷hashTable

class hashTableTest
{
   public void hashTable()
   {
            Hashtable ht = new Hashtable();
            ht.Add("boy", 24);
            ht.Add("girl", 25);            

            foreach(DictionaryEntry num in ht)
            {
                Console.Write(num.Key);
                Console.WriteLine(num.Value);
                Console.WriteLine();
    }     

}

class Program
{
   static void Main(string[] args)
   {
      hashTableTest ht = new hashTableTest();
      ht.hashTable();
      Console.ReadLine();

   }

}

output:

若我只想要知道男生人數,這時不需要遍歷hashTable,而是 ht["key"].ToString() 如下

碰到的問題 --  集合已修改列舉作業可能尚未執行

這時候你就會思考一個問題「假設我一個學期後來了好幾位轉學生有男有女,那這樣我該怎麼把這張表修正呢??」

假設今年的轉學生 僅男生 2 個 所以boy 應該為24 + 2  且印出男女各多少人數

我們來想一下,還不簡單就foreach 只要當key值為boy時 + 2 就好啦! 如下

class hashTableTest
{
        public Hashtable hashTable()
        {
            Hashtable ht = new Hashtable();
            ht.Add("boy", 24);
            ht.Add("girl", 25);          

            return ht;
        }

        public void hashTableNewStudent(Hashtable ht)
        {
            int newStudentNum = 2;
            foreach (DictionaryEntry num in ht)
            {
                if(num.Key.ToString() == "boy")
                {
                    ht["boy"] = Convert.ToInt32(num.Value) + newStudentNum;
                }
                Console.Write(num.Key);
                Console.WriteLine(num.Value);
                Console.WriteLine();
            }
 }

class Program
{
    Hashtable ht = new Hashtable();
    hashTableTest htTest = new hashTableTest();
    ht = htTest.hashTable();
    htTest.hashTableNewStudent(ht);
    Console.ReadLine();
   
}

可是這時候我卻得到這個錯誤訊息

集合已修改列舉作業可能尚未執行 ,這是一句有看沒懂得錯誤訊息。

到底什麼意思呢??

查看MSDN的說明後後發現,使用foreach走訪Dictionary時,只能讀取,不能改變內容。

The foreach statement is a wrapper around the enumerator, which allows only reading from the collection, not writing to it.

但我就是要在他走訪時去更改值啊!! 

因此我們必須改寫我們的code

解決辦法

將Dictionary的key全部取出,再用for迴圈修改Dictionary的內容。

 public void hashTableNewStudent(Hashtable ht)
{
            int newStudentNum = 2;
            string htKey = ""; 

            Console.WriteLine("尚未加入轉學生");
            foreach (DictionaryEntry num in ht)
            {
                Console.WriteLine(num.Key + " " + num.Value);               
            }
            Console.WriteLine();

            //把Dictionary的所有key放到陣列中
            string[] keyArr = new string[ht.Keys.Count];

            int k = 0;
            foreach (string htK in ht.Keys)
            {
                keyArr[k] = htK;
                k++;
            }

            Console.WriteLine("加入轉學生人數後");
            //利用陣列改變Dictionary的內容
            for (int i = 0; i < keyArr.Length; i++)
            {
                htKey = keyArr[i].ToString();
                if (htKey == "boy")
                {
                    int sum = Convert.ToInt32(ht[htKey]) + newStudentNum;
                    ht[htKey] = sum;
                }
                Console.WriteLine(htKey + " " + ht[htKey].ToString());
            }

            
}

   output


參考資料

https://ithelp.ithome.com.tw/articles/10193261

http://limitedcode.blogspot.com/2014/10/foreach-exception.html

https://gradyli.wordpress.com/2010/09/01/net-dictionary%E7%9A%84%E5%AD%98%E5%8F%96%E5%95%8F%E9%A1%8C/

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?redirectedfrom=MSDN&view=netframework-4.7.2

http://fecbob.pixnet.net/blog/post/38141041-c%23-%E6%87%89%E7%94%A8%E9%9B%9C%E6%B9%8A%E8%A1%A8%28hashtable%29-