C#中的Equals和getHashCode
Equals 的基本用法,我就不说,这里我们来看看getHashCode
hashCode主要用在hashtable类的。是为了快速的验证两个对象是否相等。
如果两个对象的hashcode不等,这两个对象就不等,
如果hashcode相等,再进一步比较equals方法。
有什好处:因为hashcode是int,比较它们是否相等速度非常快,可以提高性能。
理解一:我们先看看,GetHashCode 在对基于hashcode的集合(hashtable 和 dictionary) 基于key、value的集合的影响;
public class Person { public int ID { get; set; } public string Name { get; set; } public override bool Equals(object obj) { if(obj==null || GetType() != obj.GetType()) { return false; } return this.ID == (obj as Person).ID; } public override int GetHashCode() { int hashCode=(this.ID==0 || this.ID==null)?0:this.ID.GetHashCode(); return hashCode; } } class Program { static void Main(string[] args) { //dictionary 和 hastable 是基于hascdoe的 key的; hashcode 必须是唯一的,不重复的额 IDictionary<Person, Object> dic = new Dictionary<Person, Object>(); var p1 = new Person() { ID = 1, Name = "jack" }; var p2 = new Person() { ID = 2, Name = "tom" }; var p3 = new Person() { ID = 2, Name = "tom" }; dic.Add(p1, "1"); dic.Add(p2, "2"); dic.Add(p3, "3"); Console.WriteLine(p2.Equals(p3)); //如果仅仅是重写我们的equals的话,我们的p2 和p3 将白视作相等的对象; //然后他们的hashcode 却不是相等的; //而且我们的额每次运行,都会得到不同的值; Console.WriteLine(p2.GetHashCode()); Console.WriteLine(p3.GetHashCode()); Console.WriteLine("contains"); if (dic.ContainsKey(p3)) { //如果仅仅是重写我们的euqals的话,在被添加到我们的基于key的hashtable 中 //就会出现重复(严格意义上,说是我们的对象值,但引用不同,因为都是通过new 出来的不同对象),违反我hashtable的 不可重复性 Console.WriteLine("contains"); } else { //所以要保证hashtable的完整性,我们这里就要重写gethashCode() //我们把判断重复的基准定义为我们的额id,当然也可以多个 Console.WriteLine("no"); //ps 如果你重写gethashcode,你走不到这一步来就报错:已添加了具有相同键的项。 }
理解二:
尽量用最快的时间对对象进行初步判断
public class Person { public int Id { get; set; } public Person(int i) { Id = i; } public override bool Equals(object obj) { Console.WriteLine("call Equals"); if (obj == null || GetType() != obj.GetType()) { return false; } return Id == (obj as Person).Id; } public override int GetHashCode() { Console.WriteLine("call GetHashCode"); return Id % 2; } } class Program { static void Main(string[] args) { var p1 = new Person(1); var p2 = new Person(2); var p3 = new Person(3); var dic = new Dictionary<Person, object>(); dic.Add(p1,1); Console.WriteLine("----------------"); dic.ContainsKey(p1); Console.WriteLine("----------------"); dic.ContainsKey(p2); Console.ReadLine(); } }
执行结果:
正如我们所料的,先调用getHashCode,如果,hashCode相等,就会接着掉我们的equals 来判断,自定义对象是否相等;
当GetHashCode可以直接分辨出不相等时,Equals就没必要调用了,而当GetHashCode返回相同结果时,Equals方法会 被调用从而确保判断对象是否真的相等。所以,
还是那句话:GetHashCode没必要一定把对象分辨得很清楚(况且它也不可能,一个int不可能代表所 有的可能出现的值),有Equals在后面做保障。GetHashCode仅需要对对象进行快速判断。GetHashCode没必要一定把对象分辨得很清楚
(况且它也不可能,一个int不可能代表所 有的可能出现的值)
实例说话:
.... 未完待续;
这里补充一个好文章:
http://blog.jobbole.com/90593/
关于hascode的建议:
http://book.51cto.com/art/201109/292340.htm
对等比较:
http://www.cnblogs.com/souliid/p/5718968.html
http://blog.csdn.net/lan_liang/article/details/50234439