【问题标题】:Will Guid.GetHashCode() return different value with different AppDomain?Guid.GetHashCode() 是否会使用不同的 AppDomain 返回不同的值?
【发布时间】:2014-10-26 05:50:57
【问题描述】:

根据 MSDN:http://msdn.microsoft.com/en-us/library/system.string.gethashcode%28v=vs.110%29.aspx

相同字符串的String.GetHashCode() 可能因以下原因而不同:

  1. .NET Framework 的不同版本。

  2. 不同的平台(如 32 位和 64 位)。

  3. 甚至是不同的应用领域。

Guid.GetHashCode() 怎么样?以上3种情况会发生变化吗?

我检查了 2,Guid.GetHashCode() 确实返回不同的值。

更新

关于String.GetHashCode()如何理解3?假设我两次运行同一个应用程序,肯定有 2 个不同的应用程序域。但正如我所尝试的,只要目标平台不改变,哈希码总是相同的。例如,“你好,世界”.GetHashCode()。

那么 3 什么时候会发生?

这是我的一些问题背景:

我的服务器应用程序从客户端接收一些 GUID。 GUID 对于每个客户端都是唯一的。我想将客户端分配到不同的存储桶。而且我需要保持客户端-存储桶映射固定。有很多客户,所以我无法将所有看到的客户都保存在内存中。

我目前的解决方案是:

  1. 获取客户端 GUID 的哈希码(GUID 或 GUID 字符串,尚未确定)。
  2. 使用(HashCode % 桶总数)作为桶索引。

我必须确保特定客户端的哈希码保持不变。

【问题讨论】:

  • 为什么你需要知道这个?为什么在 32 位和 64 位上执行的相同代码给出不同的哈希码会很重要?
  • 不,它没有。你的 2. 测试不太可能是正确的,第二次运行它时你会得到一个不同的 guid :) 它的实现is very simple。 String.GetHashCode() 得到了很多额外的关注,因为它经常被使用并且具有安全隐患。 Details here.
  • 如果您需要一种不受您无法控制的更改影响的可靠哈希码实现,您应该自己实现一个。 GetHashCode 被明确记录为不被持久化,因此您不能相信计算会保持不变。一个微不足道的 .NET 修补程序可能会在您的应用程序下更改它。

标签: .net hash


【解决方案1】:

继承自System.ObjectGetHashCode 方法在documentation 中带有此消息:

哈希码用于在基于哈希表的集合中进行高效插入和查找。哈希码不是永久值。出于这个原因:
* 不要序列化哈希码值或将它们存储在数据库中。
* 不要使用哈希码作为键从键控集合中检索对象。
* 不要跨应用程序域或进程发送哈希码。在某些情况下,可以基于每个进程或每个应用程序域计算哈希码。
* 如果您需要加密的强散列,请勿使用散列码代替加密散列函数返回的值。对于加密哈希,请使用派生自 System.Security.Cryptography.HashAlgorithm 或 System.Security.Cryptography.KeyedHashAlgorithm 类的类。
* 不要测试哈希码的相等性以确定两个对象是否相等。 (不相等的对象可以具有相同的哈希码。)要测试相等,请调用 ReferenceEquals 或 Equals 方法。

(我的重点)

所以不管它当前是否真的返回不同的值,你都应该假设它可以。

至于你的 3 个具体案例,答案是:

  1. 可能
  2. 可能
  3. 可能

这就是重点

简而言之,如果您需要为您的字符串或 guid 或其他任何东西提供可靠的哈希码实现,它可以持久化,并且不会受到所列内容(或您无法控制的任何其他内容)的影响,那么您需要实现自己动手。

您可以实现 IEqualityComparer<T>,大多数使用哈希码进行键控的 .NET 集合都可以提供一个实现该接口的自定义对象,因此您甚至可以为这些对象提供自己的哈希码实现。

【讨论】:

    【解决方案2】:

    其他答案是完全正确的 - 因为它没有记录,所以您不应该依赖 GUID 的哈希码在多个应用程序域中保持一致。

    也就是说,出于好奇,这里是正在使用的实现(来自Reference Source),实际上确实似乎是一个稳定的实现,只使用组成 GUID 的字节:

    public override int GetHashCode()
    {
        return _a ^ (((int)_b << 16) | (int)(ushort)_c) ^ (((int)_f << 24) | _k);
    }
    

    【讨论】:

      【解决方案3】:

      Guid.GetHashCode 的文档非常简单;它没有定义如何计算哈希码。因此,您应该假设 Object.GetHashCode 的所有警告都适用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-09
        • 2018-08-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多