【问题标题】:Will GetHashCode method return different result for an object between different AppDomain?GetHashCode 方法会为不同 AppDomain 之间的对象返回不同的结果吗?
【发布时间】:2014-09-03 11:30:16
【问题描述】:

this Eric博客,

规则:GetHashCode 的消费者不能依赖它随着时间的推移或跨应用程序域而保持稳定。 假设您有一个 Customer 对象,该对象具有一堆字段,例如名称、地址等。如果您在两个不同的进程中创建两个具有完全相同数据的此类对象,则它们不必返回相同的哈希码。如果您在星期二在一个进程中创建这样的对象,然后将其关闭,然后在星期三再次运行该程序,则哈希码可能会有所不同。 这在过去曾咬人。 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();
    }
}

我将产品属性对象的哈希值保存在数据库中以进行更改跟踪。意味着哈希码会告诉我对象是否改变。如果可以在应用程序域之间更改哈希,那么另一种方式是什么?

【问题讨论】:

  • 这不是GetHashCode 的用途。事实上,这正是您不应该使用它的目的。为什么不使用version 列或类似的东西呢?
  • GetHashCode 的值在对象创建后不允许更改。您不能将其基于可变的字段/属性。唯一可以将哈希码基于属性的情况是当这些属性是只读的并在构造函数中设置时。如果哈希码发生变化,字典之类的东西就会失败。
  • @Enigmativity,我说的是不同 AppDomain(或进程)上的相同对象或在不同日期打开 exe。
  • @user960567 - 是的,我知道。但我说的是您在问题中发布的代码。以这种方式实现GetHashCode是错误的。

标签: c# hash


【解决方案1】:

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

不要那样做。这几乎就是要求哈希码随时间稳定的定义。老实说,AppDomain 与此无关。

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

【讨论】:

  • 抱歉,请举个例子。我正在使用控制台应用程序?
  • @user960567:好吧,我建议使用BinaryWriterProduct 对象有效地序列化为字节数组——然后您可以使用SHA256 来获得该数据的稳定散列。其中哪一部分被证明是一个问题? (可以在控制台应用程序中完成所有这些操作。)
【解决方案2】:

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

GetHashCode() 不适合那个。 保证 - 实际上字符串的算法(以及结果)现在已经改变了两次,IIRC - 现在可以按照建议为每个应用程序域提供不同的结果。

但更多:它不会告诉您所有更改。哈希码差异告诉您不相等,但获得 same 哈希码 not 告诉您相等。不是必须的。

您需要为此使用可靠的已知可重复哈希算法;也许是某种序列化形式的 SHA1 哈希,其中序列化结果本身保证是可靠的。注意:这个仍然不能保证发现所有的变化,但它发生冲突的可能性要小得多。

【讨论】:

  • 举个例子会很有帮助。
猜你喜欢
  • 2016-04-10
  • 2022-11-29
  • 1970-01-01
  • 2014-12-24
  • 2019-05-31
  • 1970-01-01
  • 2014-10-26
  • 2015-10-20
相关资源
最近更新 更多