您的位置:首页 > Web前端

Effective C#阅读笔记-7GetHashCode陷阱

2011-08-13 00:28 323 查看
GetHashCode只有在一种情况下会使用:在基于Hash的集合容器中计算key(键值)时会用到,类似Hashtable和Dictionary。对于默认的System.Object.GetHashCode(). 方法对于引用类型是可以正常工作的的但是效率底下,但是对于值类型通常是有问题的。

GetHashCode() is used in one place only: to define the hash value for keys in a hash-based collection, typically the
Hashtable or Dictionary containers.

如果需要为自己的类重写GetHashCode()方法,需要满足一下三个原则:

1. 如果连个对象是相等的(操作符定义operator==),那么两个对象的GetHashCode方法需要返回相同的值,否则将不能在容器中通过hash码取出对象

If two objects are equal (as defined by operator==), they must generate the same hash value. Otherwise, hash codes can't be used to find objects in containers.

2.对于任何一个对象,GetHashCode任何时候返回的值都是一样的,是实例不变的,一个对象只有一个HashCode,无论调用任何方法返回的HashCode都是一样的。
For any object A, A.GetHashCode() must be an instance invariant. No matter what methods are called onA,
A.GetHashCode() must always return the same value. That ensures that an object placed in a bucket is always in the right bucket.
3.Hash函数能够针对所有的Inputs生成一个比较好的分布,而不出现碰撞。
The hash function should generate a random distribution among all integers for all inputs. That's how you get efficiency from a hash-based container.
对于引用类型,默认的GetHashCode()原理为,每一个对象创建的时候都为唯一分配一个递增的整数标识符,创建以后这个标识符将不能修改,GetHashCode返回的就是这个值

Object.GetHashCode() uses an internal field in theSystem.Object class to generate the hash value. Each object created is assigned a unique object key, stored as an integer, when it is created. These keys start at1
and increment every time a new object of any type gets created. The object identity field is set in theSystem.Object constructor and cannot be modified later.
Object.GetHashCode() returns this value as the hash code for a given object.
对于值类型,System.ValueType 重写了GetHashCode()方法,返回类型定义里面第一个字段的hashcode。因此对于自定义的值类型,如果要作为hash容器的key,需要自定义GetHashCode()函数,保证能够满足上面的三个原则。

public struct MyStruct
{
private string   _msg;
private int      _id;
private DateTime _epoch;
}


如上面所示:MyStruct对象返回的hashcode,为_msg字段的hashcode.下面的语句将会一直返回为true

MyStruct s = new MyStruct( );
return s.GetHashCode( ) == s._msg.GetHashCode( );


GetHashCode() has very specific requirements: Equal objects must produce equal hash codes, and hash codes must be object invariants and must produce an even distribution to be efficient. All three can be satisfied only for immutable
types. For other types, rely on the default behavior, but understand the pitfalls.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: