开发者

What is the purpose of the tilde in this situation?

开发者 https://www.devze.com 2023-04-08 14:27 出处:网络
What could be the purpose of the tilde in this code block? public override int GetHashCode() { return ~this.DimensionId.Id ^ this.ElementId.Id;

What could be the purpose of the tilde in this code block?

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

^ Operator (C# Reference) Visual Studio 2010 Binary ^ operators are predefined for the integral types and bool. For integral types, ^ computes the bitwise exclusive-OR of its operands. For bool operands, ^ computes the logical exclusive-or of its operands; that is, the result is true if and only if exactly one of its operands is true.

~ Operator (C# Reference) Visual Studio 2010 The ~ operator performs a bitwise complement operation on its operan开发者_Python百科d, which has the effect of reversing each bit. Bitwise complement operators are predefined for int, uint, long, and ulong.

The ~ (tilde) operator performs a bitwise complement on its single integer operand. (The ~ operator is therefore a unary operator, like ! and the unary -, &, and * operators.) Complementing a number means to change all the 0 bits to 1 and all the 1s to 0s

What would be a reason why it would be used in this context (as opposed to simply excluding it)?


It's simply one way of generating a hash code. I'm not a huge fan of XORs in hash codes unless you want something that's order-independent, but it's a reasonable way of flipping bits in a reasonably arbitrary but repeatable way.

Basically you've got two 32-bit values here, which you need to combine in some form to create another 32-bit value. The code could have just XORed the values together without any bitwise complement:

return DimensionId.Id ^ ElementId.Id;

... but that would always give zero for cases where ElementId.Id == DimensionId.Id, which probably isn't ideal. On the other hand, we now always end up with -1 if the two IDs are the same, as noted in comments (doh!). On the other hand, it makes the pair {6, 4} have a different hash code to {4, 6} whereas a simple XOR doesn't... it makes the ordering important, in other words. Again, that could be important if your real identifiers are likely to be taken from a relatively small pool.

The XOR itself makes sure that a change to any bit in either ID makes a difference to the final hashcode.

Personally I normally follow Josh Bloch's pattern from effective Java, e.g.

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

... but that's just because of some of the properties of hashing that way1, and it doesn't make the implementation you've shown "wrong" in any sense.


1 It seems to work pretty well at producing distinct values in a number of common scenarios. Obviously it can't prevent hash collisions, but if your IDs are actually generated from a sequence of 1, 2, 3... then this will do better at real-life collisions that an XOR. I did see a web page analyzing this approach and which numbers work well etc, but I can't remember where.

0

精彩评论

暂无评论...
验证码 换一张
取 消