C# 中GetHashCode 与Equals

今天说一下C# 中重写public override int GetHashCode()与 public override bool Equals(object obj)

假设我们有Person 类, 向给基于Hash的Collection(比如HashTable和Dictionary)的Key定义Hash值, 有个两个Person 实例 id 不同 ,但是名字相同

代码如下:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGetHashCode
{
class Program
{
static void Main(string[] args)
{

IDictionary<Person, Object> dic = new Dictionary<Person,Object>();

Person p1 = new Person();
p1.Id = 1;
p1.Name = "name1";
p1.Age = 20;
dic.Add(p1, "111");

Person p2 = new Person();
p2.Id = 2;
p2.Name = "name2";
p2.Age = 20;
dic.Add(p2, "222");

if (dic.ContainsKey(p1))
{
Console.WriteLine("Contains");
}
else
{
Console.WriteLine("Not Contains");
}


// IList<Person> list = new List<Person>();


}


}


class Person
{

private object parent;

public object Parent
{
get { return parent; }
set { parent = value; }
}
private int id;

public int Id
{
get { return id; }
set { id = value; }
}
private string name;
private int age;

public int Age
{
get { return age; }
set { age = value; }
}

public string Name
{
get { return name; }
set { name = value; }
}

public override int GetHashCode()
{
Console.WriteLine("In GetHashCode");
// Random num = new Random();
// int a = num.Next(1,100);
int hashCode = (this.Id == 0 || this.Id == null) ? 0 : this.Id.GetHashCode();
if (this.parent != null)
{
hashCode = 31 * hashCode + this.parent.GetHashCode();
}
return hashCode;
}


public override bool Equals(object obj)
{
Console.WriteLine("Equal 被执行");

if (obj == null || GetType() != obj.GetType())
{
return false;
}

return this.Id == (obj as Person).Id;
}

}
}


在执行 dic.Add(p1, "111"); 时候只会调用GetHashCode。
在执行 dic.Add(p2, "222"); 时候只会调用GetHashCode 不会调用Equals方法,
如果把Person p2的Id 改成和 P1的Id 改成一样则会报ArgumentException {"An item with the same key has already been added."}
这样就可以防止有相同Id 的Person 实例被添加到集合中

所以这样可以证明两个实体相等,他们的HashCode一定相等,但是HashCode相等,两个实体不一定相等

在执行if (dic.ContainsKey(p1))时,会先调用p1的GetHashCode方法,再调Equals方法。

如果我们修改程序,让Id 可以相同,但名字不同的人也可以加入集合dic


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGetHashCode
{
class Program
{
static void Main(string[] args)
{

IDictionary<Person, Object> dic = new Dictionary<Person,Object>();

Person p1 = new Person();
p1.Id = 1;
p1.Name = "name1";
p1.Age = 20;
dic.Add(p1, "111");

Person p2 = new Person();
p2.Id = 1;
p2.Name = "name2";
p2.Age = 20;
dic.Add(p2, "222");

if (dic.ContainsKey(p1))
{
Console.WriteLine("Contains");
}
else
{
Console.WriteLine("Not Contains");
}





}


}


class Person
{

private object parent;

public object Parent
{
get { return parent; }
set { parent = value; }
}
private int id;

public int Id
{
get { return id; }
set { id = value; }
}
private string name;
private int age;

public int Age
{
get { return age; }
set { age = value; }
}

public string Name
{
get { return name; }
set { name = value; }
}

public override int GetHashCode()
{
Console.WriteLine("In GetHashCode");
// Random num = new Random();
// int a = num.Next(1,100);
int hashCode = (this.Id == 0 || this.Id == null) ? 0 : this.Id.GetHashCode();
if (this.parent != null)
{
hashCode = 31 * hashCode + this.parent.GetHashCode();
}
return hashCode;
}


public override bool Equals(object obj)
{
Console.WriteLine("Equal 被执行");

if (obj == null || GetType() != obj.GetType())
{
return false;
}

return this.Id == (obj as Person).Id && this.Name == (obj as Person).Name;
}

}
}



在执行 dic.Add(p2, "222"); 时候除了会调用GetHashCode外,还会调用Equals方法

在执行if (dic.ContainsKey(p1))时,会先调用p1的GetHashCode方法,再调Equals方法。 这次会调用两次Equals方法,因为这个时候p1 和 p2在 dic集合里面的HashCode都是一样的。 第一次会让传入的obj和p2进行比较,然后会和p1 和 obj进行比较,最终输出Contains

Java 中这块的原理和C#相同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值