2014-09-03 24 views
0

this Eric博客,GetHashCode方法会为不同的AppDomain之间的对象返回不同的结果吗?

规则:GetHashCode的消费者不能依靠它随着时间的过去或跨应用程序域稳定。 假设您有一个Customer对象,其中包含诸如Name,Address等字段。如果在两个不同的进程中使两个这样的对象具有完全相同的数据,则它们不必返回相同的哈希码。如果星期二在一个进程中创建了这样一个对象,关闭它,并在周三再次运行该程序,哈希代码可能会不同。 这已经让过去的人感到困扰。 System.String.GetHashCode的文档特别指出,两个相同的字符串可以在CLR的不同版本中具有不同的哈希码,事实上它们的确可以。不要在数据库中存储字符串哈希值,并期望它们永远保持不变,因为它们不会。

我使用这个类,

public class Product 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string ModelNumber { get; set; } 
    public string Sku { get; set; } 
    public string Description { get; set; } 
    public double Price { get; set; } 
    public double NewPrice { get; set; } 

    public override int GetHashCode() 
    { 
     return Id^(Name ?? "").GetHashCode()^(ModelNumber ?? "").GetHashCode()^(Sku ?? "").GetHashCode()^ (Description ?? "").GetHashCode()^Price.GetHashCode()^NewPrice.GetHashCode(); 
    } 
} 

我节省了产品性能的哈希对象在数据库中更改跟踪。意味着哈希码会告诉我对象是否改变了。如果可以在应用程序域之间更改散列,那么另一种方式是什么?

+0

这不是'GetHashCode'的用途。事实上,这正是你*不应该使用它的原因。为什么不使用'version'列或类似的东西呢? – Luaan 2014-09-03 11:36:02

+0

创建对象后,不允许更改'GetHashCode'的值。你**不能**基于可变的字段/属性。唯一一次可以将哈希码作为属性的基础是那些属性只能在构造函数中读取和设置。如果字典代码改变,像字典这样的东西就会失败。 – Enigmativity 2014-09-03 12:35:34

+0

@Enigmativity,我在不同的AppDomain(或进程)上说同一个对象,或者在不同的日子打开exe。 – user960567 2014-09-03 12:37:06

回答

4

我将产品属性对象的散列保存在数据库中以进行更改跟踪。

不这样做。这几乎是要求散列码随时间稳定的定义。说实话,AppDomain与此无关。

如果你需要某种形式的散列这稳定,您可能希望将对象转换为稳定的二进制表示(例如,使用BinaryWriter),然后取一个SHA-256散列 - 因为SHA-256(和类似的加密哈希)被设计为稳定。

+0

对不起,但请建议一个例子。我使用控制台应用程序? – user960567 2014-09-03 12:10:32

+2

@ user960567:那么我建议使用'BinaryWriter'来有效地将你的'Product'对象序列化为一个字节数组 - 然后你可以使用'SHA256'来获得一个稳定的数据散列。哪部分被证明是一个问题? (在控制台应用程序中完成所有这些操作很好。) – 2014-09-03 12:22:48

4

我将产品属性对象的散列保存在数据库中以进行更改跟踪。

GetHashCode()是不适合的。这是不是保证 - 实际上字符串的算法(因此结果)现在已经改变了两次,IIRC - 现在可以给每个应用程序域不同的结果,如所建议的。

但更多:它并没有告诉你所有的变化。哈希码的区别告诉你关于不等于,但获得相同的哈希码而不是告诉你关于平等。这不是必需的。

您需要使用可靠的已知可重复哈希算法;也许是一些序列化形式的SHA1哈希,其中序列化结果本身保证是可靠的。注意:这仍然将不能保证发现所有的变化,但它会大大减少碰撞的可能性。

+0

一个示例会很有帮助。 – user960567 2014-09-03 12:05:40

相关问题