我正在尝试获取一个对象的散列(md5或sha)。
我实现了这个:http://alexmg.com/post/2009/04/16/Compute-any-hash-for-any-object-in-C.aspx
我正在使用nHibernate从数据库中检索POCO。
在此运行GetHash时,每次从数据库中选择和水合它时都会有所不同。我想这是意料之中的,因为底层代理将改变。
总之
有没有一种方法可以得到一个对象的所有属性的散列,每次都是一致的?
我曾经尝试过在上面使用StringBuilder。GetType().GetProperties.....并创建一个散列,但这似乎效率很低?
顺便说一下,这是为了跟踪这些实体从一个数据库(RDBMS)到NoSQL存储的更改(比较哈希值以查看对象是否在rdbms和nosql之间更改)
4条答案
按热度按时间lhcgjxsq1#
如果你没有覆盖
GetHashCode
,你只是继承了Object.GetHashCode
。Object.GetHashCode
基本上只是返回示例的内存地址,如果它是一个引用对象。当然,每次加载对象时,它可能会被加载到内存的不同部分,从而导致不同的哈希码。这是否是正确的做法是有争议的;但这是“过去”实施的,所以现在不能改变。
如果你想要一致的东西,那么你必须覆盖
GetHashCode
,并根据对象的“值”创建一个代码(即属性和/或字段)。这可以像所有属性/字段的散列代码的分布式合并一样简单。或者,它可以像你需要的那样复杂。如果您所寻找的只是区分两个不同对象的东西,那么对对象使用唯一键可能会对您有用。如果您正在寻找更改跟踪,则对散列使用唯一键可能不起作用我只是使用字段的所有哈希代码为父对象创建一个合理分布的哈希代码。例如:
素数397的使用是为值生成唯一的数字以更好地分发散列码。有关在哈希码计算中使用素数的更多详细信息,请参见http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/。
当然,您可以使用反射来获取所有属性,但这样会比较慢。或者,您可以使用CodeDOM动态生成代码,以根据属性的反射生成哈希,并缓存该代码(即生成一次,下次重新加载)。但是,这当然是非常复杂的,可能不值得付出努力。
MD5或SHA散列或CRC通常基于数据块。如果你想这样做,那么使用每个属性的哈希码是没有意义的。可能将数据序列化到内存中并以这种方式计算散列将更适用,正如Henk所描述的那样。
bvjxkvbb2#
如果该“散列”仅用于确定实体是否已更改,则以下算法可能会有所帮助(注意,它未经测试,并假设在生成散列时将使用相同的运行时(否则,对于“简单”类型依赖GetHashCode是不正确的)):
这样就可以像这样使用:
vs3odd8k3#
在寻找简单的东西时遇到了这个问题。我最终做到了这一点:
kkih6yb84#
GetHashCode()返回Int32(不是MD5)。
如果你创建了两个具有相同属性值的对象,如果你使用了base或system GetHashCode(),它们将不会有相同的Hash。
字符串是一个对象和一个异常。
如果你想控制两个对象的相等性比较,那么你应该覆盖GetHash和Equality。
如果两个对象是相同的,那么它们也必须具有相同的GetHash()。但是具有相同GetHash()的两个对象不一定相同。比较将首先测试GetHash(),如果它在那里得到匹配,它将测试Equals。好吧,有一些直接进入Equals的比较,但你仍然应该覆盖两者,并确保两个相同的对象产生相同的GetHash。
我用它来同步客户端和服务器。您可以使用所有属性,也可以更改任何属性以更改VerID。这里的优点是更简单更快的GetHashCode()。在我的例子中,我已经用任何属性更改重置了VerID。
最后我只使用ObjID,这样我就可以做以下事情
Object.GetHashCode Method
具有相同特性值的两个对象。他们是平等的吗?它们是否产生相同的GetHashCode()?