积极答复者
怎样让HashTable认为两个同值对象相等?

问题
-
以下是我的代码,其中a1和a3拥有相同的值。两个对象的Equals()方法返回为true,但是用到HashTable中就为False了。
请问怎样让HashTable认为两个同值对象相等?using System;
namespace ConsoleApplication3
{
class Age
{
private int _year;
public Age(int year)
{
_year = year;
}
public int Year
{
get
{
return this._year;
}
}
public override bool Equals(object obj)
{
Age a = (Age)obj;
return a._year == this._year;
}
public override int GetHashCode()
{
return base.GetHashCode() ^ _year;
}
}
class Program
{
static void Main(string[] args)
{
System.Collections.Hashtable ageList = new System.Collections.Hashtable();
Age a1 = new Age(123);
ageList.Add(a1, a1);
Age a2 = new Age(567);
ageList.Add(a2,a2);Age a3 = new Age(123);
Console.WriteLine(a1.Year);
Console.WriteLine(a3.Year);bool boolean = a3.Equals(a1);
Console.WriteLine(boolean);bool boolean2 = ageList.Contains(a3);
Console.WriteLine(boolean2);Console.Read();
/*
* 运行结果:
* 123
* 123
* True
* False
*/
}
}
}
做最好的自己- 已移动 Sheng Jiang 蒋晟Moderator 2009年8月11日 16:07 .Net基础类库问题 (发件人:Visual C#)
答案
-
你好a3.Equals(a1)是根据你的重载
public override bool Equals(object obj)
{
Age a = (Age)obj;
return a._year == this._year;
}
来判断的 这里的a3的_year和a1的相等都是值类型的int 均为123 因此返回的是true
但是 bool boolean2 = ageList.Contains(a3); 则是确定这个HashTable是否包含了a3 当你用 bool boolean2 = ageList.Contains(a2);或者 bool boolean2 = ageList.Contains(a1);由于他们都是引用类型,你添加了a1和a2到hashTable的 所以返回为True 但是由于a3你是没有添加的所有返回为false,如果你是要判断HashTable是否存在某个Age对象的实例它的_year和你传入的Age对象的_year相等,可以通过遍历的方式
bool ContainsAge(Age a)
{
foreach(Object htA in ageList.Keys)
{
bool contains=(Age)htA.Equals(a);
if(contains)
{
return true;
}
}
return false;
}
Wenn ich dich hab’,gibt es nichts, was unerträglich ist.坚持不懈!http://hi.baidu.com/1987raymond- 已标记为答案 NineTyNine_LiPei 2009年8月9日 10:48
-
Hashtable 的key必须是唯一的 不然失去Hashtable的key意义
你在hashtable取出对象才能比较- 已标记为答案 NineTyNine_LiPei 2009年8月9日 10:49
-
您好,HashTable的Contains方法是依靠返回的Key对象的哈希值来判断哈希表中是否包含该对象。
很明显a3不在HashTable中。正确的使用方法应当不是您设计的代码。但有一个小技巧可以达到您希望的效果。
将public override int GetHashCode()
{
return base.GetHashCode() ^ _year;
}
改为
public override int GetHashCode()
{
return _year;
}- 已标记为答案 NineTyNine_LiPei 2009年8月9日 10:49
-
感谢楼上各位的答复。
在此我想请教一下“jiyuan”:
GetHashCode()有什么作用?为什么函数改成那样就可以让HashTable认为两个同值异对象相同呢?
做最好的自己
您好,在调用HashTable中的void Add(Object key, Object value)方法添加一个key/value对时,key对象的哈希值也被存储。这个哈希值则是从key对象的GetHashCode()方法中得来。
而在遍历查询时,会根据这个哈希值做key的比对。可以简单理解为HashTable中的key是由key对象的哈希值来决定的。因此当这个哈希值相等时HashTable就认为比较的两个对象相等。
如果按我上面给的方法修改,您会发现在您给的例子中,尝试添加a3会失败。因为a1与a3的哈希值相等。HashTable认为对象已存在。- 已标记为答案 NineTyNine_LiPei 2009年8月10日 3:06
全部回复
-
你好a3.Equals(a1)是根据你的重载
public override bool Equals(object obj)
{
Age a = (Age)obj;
return a._year == this._year;
}
来判断的 这里的a3的_year和a1的相等都是值类型的int 均为123 因此返回的是true
但是 bool boolean2 = ageList.Contains(a3); 则是确定这个HashTable是否包含了a3 当你用 bool boolean2 = ageList.Contains(a2);或者 bool boolean2 = ageList.Contains(a1);由于他们都是引用类型,你添加了a1和a2到hashTable的 所以返回为True 但是由于a3你是没有添加的所有返回为false,如果你是要判断HashTable是否存在某个Age对象的实例它的_year和你传入的Age对象的_year相等,可以通过遍历的方式
bool ContainsAge(Age a)
{
foreach(Object htA in ageList.Keys)
{
bool contains=(Age)htA.Equals(a);
if(contains)
{
return true;
}
}
return false;
}
Wenn ich dich hab’,gibt es nichts, was unerträglich ist.坚持不懈!http://hi.baidu.com/1987raymond- 已标记为答案 NineTyNine_LiPei 2009年8月9日 10:48
-
Hashtable 的key必须是唯一的 不然失去Hashtable的key意义
你在hashtable取出对象才能比较- 已标记为答案 NineTyNine_LiPei 2009年8月9日 10:49
-
您好,HashTable的Contains方法是依靠返回的Key对象的哈希值来判断哈希表中是否包含该对象。
很明显a3不在HashTable中。正确的使用方法应当不是您设计的代码。但有一个小技巧可以达到您希望的效果。
将public override int GetHashCode()
{
return base.GetHashCode() ^ _year;
}
改为
public override int GetHashCode()
{
return _year;
}- 已标记为答案 NineTyNine_LiPei 2009年8月9日 10:49
-
感谢楼上各位的答复。
在此我想请教一下“jiyuan”:
GetHashCode()有什么作用?为什么函数改成那样就可以让HashTable认为两个同值异对象相同呢?
做最好的自己
您好,在调用HashTable中的void Add(Object key, Object value)方法添加一个key/value对时,key对象的哈希值也被存储。这个哈希值则是从key对象的GetHashCode()方法中得来。
而在遍历查询时,会根据这个哈希值做key的比对。可以简单理解为HashTable中的key是由key对象的哈希值来决定的。因此当这个哈希值相等时HashTable就认为比较的两个对象相等。
如果按我上面给的方法修改,您会发现在您给的例子中,尝试添加a3会失败。因为a1与a3的哈希值相等。HashTable认为对象已存在。- 已标记为答案 NineTyNine_LiPei 2009年8月10日 3:06