【问题标题】:Does DateTime.Now have its own implementation of GetHashCode that gives unique hashes?DateTime.Now 是否有自己的 GetHashCode 实现来提供唯一的哈希值?
【发布时间】:2010-01-02 02:56:49
【问题描述】:

MSDN 文章here 指出,GetHashCode() 的默认实现不保证唯一的结果,不应用作标识符。所以我的问题是 DateTime.Now 是否有自己的实现来给出唯一的哈希值。谢谢帮助

【问题讨论】:

  • 这个问题的表述有些奇怪。 DateTime 结构具有 GetHashCode() 的实现。 DateTime.Now 是一个静态属性,它返回一个 DateTime 实例。

标签: c# datetime gethashcode


【解决方案1】:

首先,将GetHashCode 的特定实现依赖于DateTime 是错误的。那是对你隐藏的东西。依赖隐藏的细节是不好的代码味道;他们可能随时改变你并破坏你的代码。

其次,事实证明DateTime 内部存储了一个 64 位整数 DateTime.Ticks,它测量自纪元(0001 年 1 月 1 日午夜)以来 100 纳秒单位的数量。因此,DateTime 实例至少需要 64 位信息。但是哈希码是 32 位整数,因此哈希码不能是唯一的(不能将 64 位空间映射到 32 位空间而不会发生冲突)。

明确地说,可以看DateTime.GetHashCode的源码:

public override int GetHashCode() {
    long internalTicks = this.InternalTicks;
    return (((int) internalTicks) ^ ((int) (internalTicks >> 0x20)));
}

如您所见,它做了一些“折叠”以将InternalTicks 压缩成一个 32 位整数。

一般来说,不要依赖哈希码是唯一的。输入空间通常大于被散列到的空间(所有 32 位整数的空间)。

如果您绝对必须有一个唯一键来表示DateTime 对象,请使用DateTime.ToBinary。这将为您提供一个唯一的 64 位整数,可用于重构 DateTime(使用 DateTime.FromBinary)。

【讨论】:

  • 另一个细节:GetHashCode 不考虑DateTimeKind(可以是本地、UTC 或未指定)。 ToBinary 会。
【解决方案2】:

不,它没有。

DateTime 在内部将其值存储为 long,其中包含自 01/01/0001 以来的 100 纳秒单位。

由于GetHashCode返回的是一个32位的整数,所以它不可能是完全unqiue。

这是DateTime的实现:

public override int GetHashCode() {
    Int64 ticks = InternalTicks;
    return unchecked((int)ticks) ^ (int)(ticks >> 32); 
}

【讨论】:

  • 嗯,为什么你的不一样?
  • 同理,编译器去掉了不必要的unchecked关键字。
【解决方案3】:

DateTime.Now 返回一个 DateTime 值,我确信它有自己的哈希码实现。这是实现。

public override int GetHashCode()
{
    long internalTicks = this.InternalTicks;
    return (((int) internalTicks) ^ ((int) (internalTicks >> 0x20)));
}

【讨论】:

    猜你喜欢
    • 2013-12-21
    • 2010-09-13
    • 2018-04-24
    • 2010-10-15
    • 2011-02-15
    • 2018-06-23
    • 1970-01-01
    • 2016-03-05
    • 2019-02-03
    相关资源
    最近更新 更多