c# - 在这种情况下波浪号的目的是什么?

标签 c#

此代码块中波浪号的用途是什么?

public override int GetHashCode()
    {
      return ~this.DimensionId.Id ^ this.ElementId.Id;
    }

^ 运算符(C# 引用) Visual Studio 2010 二元 ^ 运算符是为整数类型和 bool 预定义的。对于整数类型,^ 计算其操作数的按位异或。对于 bool 操作数,^ 计算其操作数的逻辑异或;也就是说,当且仅当恰好其中一个操作数为真时,结果为真。

~ 运算符(C# 引用) Visual Studio 2010 ~ 运算符对其操作数执行按位补码运算,具有反转每一位的效果。为 int、uint、long 和 ulong 预定义了位补运算符。

~(代字号)运算符对其单个整数操作数执行按位补码。 (因此 ~ 运算符是一元运算符,就像 ! 和一元运算符 -、& 和 * 一样。)补数意味着将所有 0 位更改为 1,并将所有 1 更改为 0

为什么在此上下文中使用它(而不是简单地排除它)的原因是什么?

最佳答案

这只是生成哈希码的一种方法。我不太喜欢哈希码中的 XOR,除非你想要一些与顺序无关的东西,但这是一种以相当任意但可重复的方式翻转位的合理方式。

基本上,您在这里有两个 32 位值,您需要以某种形式组合它们以创建另一个 32 位值。代码可以只是将这些值异或在一起而不用任何按位补码:

return DimensionId.Id ^ ElementId.Id;

...但是对于 ElementId.Id == DimensionId.Id 的情况,这将始终为零,这可能并不理想。另一方面,如果两个 ID 相同,我们现在总是以 -1 结束,如评论中所述(doh!)。另一方面,它使 {6, 4} 对具有与 {4, 6} 不同的散列码,而简单的 XOR 则不会……换句话说,它使排序很重要。同样,如果您的真实标识符可能取自相对较小的池,那么这可能很重要。

XOR 本身确保对任一个 ID 中的任何 位的更改对最终哈希码产生影响。

就我个人而言,我通常遵循有效 Java 中 Josh Bloch 的模式,例如

unchecked
{
    int hash = 17;
    hash = hash * 31 + DimensionId.Id;
    hash = hash * 31 + ElementId.Id;
    return hash;
}

...但这只是因为以这种方式散列的某些属性1,并且它不会使您所展示的实现在任何意义上都是“错误的”。


1 它似乎在许多常见场景中都能很好地生成不同的值。显然它不能防止散列冲突,但是如果您的 ID 实际上是从 1、2、3 的序列生成的……那么这在现实生活中的冲突中会比 XOR 做得更好。我确实看到了一个分析这种方法的网页以及哪些数字效果很好等等,但我不记得在哪里。

关于c# - 在这种情况下波浪号的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7572276/

相关文章:

c# - 将 Action<T> 公开为 Action<object>

c# - .NET SslStream 不工作

c# - 如果匿名类型应该是不可变的,为什么可以更改它?

c# - 编辑SSIS脚本任务时可以使用ReSharper吗?

c# - 如何在 C# 中检查损坏的 TIFF 图像?

c# - 防止外部代码修改C#中的私有(private)数据

c# - 在 Visual Studio 解决方案中结合 C# 和 C++

c# - MVC3 单_ViewStart

c# - 如何读取 web api 操作过滤器中的参数属性值

c# - 将托管 unsigned char* 转换为 jbyte*