C# GetHashCode 的实现方式
2015-12-09 12:00
471 查看
在项目中,在使用哈希表时,有时会需要Override GetHashCode。这里给出一种普遍的做法:
版本1:
实现一个helper,传递类型T,返回这个类型的hashcode。函数逻辑很直接,只是做了null check而已;如果obj不为空,则直接使用obj的hash code。
为什么使用了magic number 31? 使用素数乘积可以相对增加唯一性,减少哈希键值分配时的冲突;而31则是为了编译器优化的考虑(有效的转换为i<<5-1)。大概搜了一下,这种实现方式来自JAVA中string 的hash code函数。这里有详细介绍: https://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/
实现版本2:
可以扩展这个类成为流畅接口,它可以hash各种类型的,对于值类型来说,重载的意义在于减少装箱;对于集合或泛型,则为了让外部调用更自然,可读性更强。
版本1:
实现一个helper,传递类型T,返回这个类型的hashcode。函数逻辑很直接,只是做了null check而已;如果obj不为空,则直接使用obj的hash code。
public class HashHelper { private int _seed = 17; public int Hash<T>(T obj) { // why 31? // https://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/ // shortly, to reduce the conflict of hashing key's distrabution return 31 * _seed + ((obj == null) ? -1 : obj.GetHashCode()); } }
为什么使用了magic number 31? 使用素数乘积可以相对增加唯一性,减少哈希键值分配时的冲突;而31则是为了编译器优化的考虑(有效的转换为i<<5-1)。大概搜了一下,这种实现方式来自JAVA中string 的hash code函数。这里有详细介绍: https://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/
实现版本2:
可以扩展这个类成为流畅接口,它可以hash各种类型的,对于值类型来说,重载的意义在于减少装箱;对于集合或泛型,则为了让外部调用更自然,可读性更强。
public class HashFluent { private int _seed = 17; private int _hashContext; public HashFluent Hash<T>(T obj) { // why 31? // https://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/ // shortly, to reduce the conflict of hashing key's distrabution _hashContext = 31 * _seed + ((obj == null) ? -1 : obj.GetHashCode()); return this; } public HashFluent Hash(int? value) { _hashContext = 31 * _seed + ((value == null) ? -1 : value.GetHashCode()); return this; } public HashFluent Hash(IEnumerable sequence) { if (sequence == null) { _hashContext = 31 * _hashContext + -1; } else { foreach (var element in sequence) { _hashContext = 31 * _hashContext + ((element == null) ? -1 : element.GetHashCode()); } } return this; } public override int GetHashCode (){ return _hashContext; } // add more overridings here .. // add value types overridings to avoid boxing which is important }
相关文章推荐
- C#中if和#if区别
- C#中Validating和Validated事件
- C# 之泛型详解
- C#中yield return用法分析
- C# yield关键字详解
- C#操作字符串string
- C# 继承
- C#实现简单的SmtpClient发送邮件
- c#不重复的排序方法
- C# 封装,继承,多态
- c#播放声音文件
- C#中string类型前加@标志的作用
- C#中 virtual 和 abstract 的区别
- C# 清除事件绑定的函数
- C# 清除事件绑定的函数
- 【C#】高级语言特有的单例模式
- C# implementation of dynamic hand gesture recognition
- C# 编码转换 utf8
- C# 16进制与字符串、字节数组之间的转换
- Github上十大c#开源项目排行榜