C# GetHashCode 的实现方式

在项目中,在使用哈希表时。有时会须要Override GetHashCode。

这里给出一种普遍的做法:

版本号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
}

时间: 2024-10-08 20:50:44

C# GetHashCode 的实现方式的相关文章

图片压缩之处理小图片压缩策略

在进行图片压缩的时候.有时候会碰到要压缩的图片尺寸小于指定的压缩尺寸,若直接压缩会导致图片失真. 当然.最好的方式是挑选合适尺寸图片进行上传. 这里给出的方法是:对不足尺寸部分进行空白填充. 详细參见下面代码 using System; using System.Drawing.Drawing2D; using System.Drawing; using System.IO; using System.Drawing.Imaging; namespace CommonLib { public c

Equals和GetHashcode

一.两个逻辑上相等的实例对象. 两个对象相等,除了指两个不同变量引用了同一个对象外,更多的是指逻辑上的相等.什么是逻辑上相等呢?就是在一定的前提上,这两个对象是相等的.比如说某男生叫刘益红,然后也有另外一个女生叫刘益红,虽然这两个人身高,爱好,甚至性别上都不相同,但是从名字上来说,两者是相同的.Equals方法通常指的就是逻辑上相等. 二.Object的GetHashcode方法. 计算Hashcode的算法中,应该至少包含一个实例字段.Object中由于没有有意义的实例字段,也对其派生类型的字

WebApi服务Uri加密及验证的两种方式

最近的一个项目要求服务端与UI层分离,业务层以WebApi方式向外提供所有业务服务,服务在数据保密性方面提出了要求,主要包括: 1:客户端认证: 2:服务请求超时(默认5分钟): 3:服务Get请求的参数密文传输. 以上三个需求为一般的网络服务比较常见的简单要求,在WebApi项目中也比较容易实现,以下是我采用的两种实现方式(任意一种即可): 一:继承HttpClient来加入数据(Uri)加密,加入验证Header,继承ApiController来对Header进行合法性验证,并解密Uri 客

C#语法——await与async的正确打开方式

C#5.0推出了新语法,await与async,但相信大家还是很少使用它们.关于await与async有很多文章讲解,但有没有这样一种感觉,你看完后,总感觉这东西很不错,但用的时候,总是想不起来,或者不知道该怎么用. 为什么呢?我觉得大家的await与async的打开方式不正确. 正确的打开方式 首先看下使用约束. 1.await 只能在标记了async的函数内使用. 2.await 等待的函数必须标记async. 有没有感觉这是个循环?没错,这就是个循环.这也就是为什么大家不怎么用他们的原因.

angularJs中关于ng-class的三种使用方式说明

在开发中我们通常会遇到一种需求:一个元素在不同的状态需要展现不同的样子. 而在这所谓的样子当然就是改变其css的属性,而实现能动态的改变其属性值,必然只能是更换其class属性 这里有三种方法: 第一种:通过数据的双向绑定(不推荐) 第二种:通过对象数组 第三种:通过key/value 下面简单说下这三种: 第一种:通过数据的双向绑定 实现方式: function changeClass(){   $scope.className = "change2"; } <div clas

配置resin web方式部署项目

写在前面,推荐下载resin4.0.47版本.其它版本没有测试 最近打算做一个小项目,然后容器选用了resin.想通过web提交war文件的方式 进行部署,更新代码也方便. 试了resin最新的版本(目前最新版本为4.0.53),提交war文件到webapps下面都是.tmp文件.百度google一通还是没找到解决办法. 看了下公司用的resin版本,选择4.0.47.下载后发现没最新版本的上传问题. 通过web提交war文件方式步骤如下: 步骤一:修改resin.properties.推荐配置

(转)web会话管理方式

阅读目录 1. 基于server端session的管理 2. cookie-based的管理方式 3. token-based的管理方式 4. 安全问题 5. 总结 http是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的,但是对于我们的应用来说,我们是靠用户来管理,而不是靠客户端.所以对我们的应用而言,它是需要有状态管理的,以便服务端能够准确的知道http请求是哪个用户发起的,从而判断他是否有权限继续这个请求.这

Jenkins 2.60.x 2种发送邮件方式

1.1 默认发邮件的配置方式 1.1.1 系统级别 邮件配置 1.1.2 项目级别 邮件配置 测试构建失败是否会发邮件: 控制台输出:提示已发送邮件给项目配置指定的两个邮箱地址. 1.1.2.1  查看邮箱 1.2 第三方插件 发送邮件的配置方式 1.2.1 系统级别 邮件配置 再次打开系统配置找到如下图的地方配置发送邮件的触发条件. 1.2.1 项目级别 邮件配置 控制台输出(console output): 1.2.1.1  查看邮件 确认第一个邮箱收件人 确认第二个邮箱收件人

maven 坐标获取方式

问题:我们在开发时pom.xml文件中的 <dependencies>     <dependency>         <groupId>org.mybatis</groupId>         <artifactId>mybatis</artifactId>         <version>3.2.5</version>     </dependency> </dependencies