Hashtable 中的键值修改问题

Hashtable 允许我们通过键来寻找保存在其中的值,还可以通过 ContainsKey 方法来查看是否在 Hashtable 中有对应的键,但是,在使用中还是有一些需要注意的地方。

一个同学写了这样一段使用 Hashtable 的代码,发现一个奇怪的问题。

  1  using  System;
  2  using  System.Collections.Generic;
  3  using  System.Linq;
  4  using  System.Text;
  5  using  System.Collections;
  6  using  System.Threading;
  7 
  8  namespace  HashtableDemo
  9  {
 10       class  Program
 11      {
 12           static   void  Main( string [] args)
 13          {
 14               // 第一次输出 
 15               //  not
 16              Hashtable ha  =   new  Hashtable();
 17               for  ( int  i  =   0 ; i  <   5 ; i ++ )
 18                  ha.Add( new  cuskey(i), i);
 19 
 20               if  (ha.ContainsKey( new  cuskey( 3 )))
 21                  Console.WriteLine( " find " );
 22               else
 23                  Console.WriteLine( " Can't find " );
 24 
 25              ha.Clear();
 26 
 27               // 第二次输出 
 28               //  ok
 29              MyTest t  =   new  MyTest( 10 );
 30              ha.Add(t,  10 );
 31               if  (ha.ContainsKey( new  MyTest( 10 )))
 32              {
 33                  Console.WriteLine( " find " );
 34              }
 35               else
 36                  Console.WriteLine( " Can't find " );
 37 
 38               // 第三次输出 
 39               //  ok
 40              Console.WriteLine(ha[ new  MyTest( 10 )]);
 41 
 42               // 第四次输出 
 43               //  
 44              t.KeyNum  =   11 ;
 45 
 46               if  (ha.ContainsKey( new  MyTest( 11 )))
 47              {
 48                  Console.WriteLine( " find 11 " );
 49              }
 50               else   if  (ha.ContainsKey( new  MyTest( 10 )))
 51                  Console.WriteLine( " find 10 " );
 52               else
 53                  Console.WriteLine( " Can't find " );
 54 
 55 
 56 
 57               // 第五次输出 
 58              Console.WriteLine(ha.Count);
 59 
 60               // 第六次输出 
 61              MyTest mt  =   new  MyTest( 11 );
 62              ha.Add(mt,  11 );
 63              Console.WriteLine(ha.Count);
 64 
 65               // 第七次输出 
 66               foreach  (DictionaryEntry item  in  ha)
 67              {
 68                  Console.WriteLine((item.Key  as  MyTest).KeyNum);
 69                  Console.WriteLine(item.Value);
 70              }
 71 
 72              Console.ReadLine();
 73          }
 74      }
 75 
 76       class  MyTest
 77      {
 78           int  keyNum;
 79 
 80           public   int  KeyNum
 81          {
 82               get  {  return  keyNum; }
 83               set  { keyNum  =  value; }
 84          }
 85 
 86           public  MyTest( int  num)
 87          {
 88              keyNum  =  num;
 89          }
 90 
 91           public   override   int  GetHashCode()
 92          {
 93               return  keyNum;
 94          }
 95 
 96           public   override   bool  Equals( object  obj)
 97          {
 98               return  keyNum  ==  ((MyTest)obj).KeyNum;
 99          }
100      }
101 
102       class  cuskey
103      {
104           int  keyNum;
105 
106           public   int  KeyNum
107          {
108               get  {  return  keyNum; }
109               set  { keyNum  =  value; }
110          }
111 
112           public  cuskey( int  num)
113          {
114              keyNum  =  num;
115          }
116      }
117  }

 

然后,发现一个问题:

在第四次我用了两个键去匹配,都是Can't find,但是在第七次输出的时候怎么就能找到确实是KeyNum=11的实例,这是怎么回事???


当我们在 Hashtable 中通过键来保存值的时候,Hashtable 会通过键对象的 HashCode 来确定内容保存在表中的位置,同时还要保存这个键对象的引用。

当我们通过 ContainsKey 来查找的时候,Hashtable 将会取得用来查找的键对象的 HashCode ,计算出在 Hashtable 中相应的位置,然后,在这个位置取出保存的键, 与现在的查找对象的 HashCode 去比较。

在第四次的时候,使用 11 的时候,计算出的 Hashcode 将在 11 所对应的位置。但是,原来通过 10 保存,现在使用 HashCode 11 来查找,所以,这个位置中没有保存数据,所以找不到。
在使用 10 的时候,在这个位置上有保存的键,但是,通过 Equals 方法判断两个对象不相同,所以,也找不到。

但是,在 Hashtable 中确实保存着一个条目。所以,在第七次的时候可以遍历到。

Hashtable 中的键值修改问题

所以,如果通过一个对象作为键在 Hashtable 中保存数据,那么,一旦修改了这个键对象,就可能没有办法通过键对象来找到原来保存的值。

在需要修改键对象的时候,正确的方式是,先移除原来的键值对,然后修改键对象,最后,使用修改之后的键对象来保存新的键值对。

在 CLR Via C# 中文 第三版的 130 页中间,Jeffrey 也提到了这个问题。

 

 

 

你可能感兴趣的:(Hashtable)