2

I am trying to calculate a hash code for one of my classes, the problem is: this class has a byte[] which returns a different hash for every object. I have made 2 objects of the class and both are instantiated with a new byte[0].

When overriding the Equals operator I've used Enumberable.SquenceEqual() to make sure the content of both array's are the same. But how would I make sure the arrays return the same hashcode if their contents are the same?

my code:

    public override bool Equals(object obj)
    {
        return Equals(obj as MessageType);
    }

    {
        if (messageType != null)
        {
            return (this.Identification == messageType.Identification) &&
                (this.ActivateWindow == messageType.ActivateWindow) &&
                (this.Logging == messageType.Logging) &&
                (Enumerable.SequenceEqual(this.Pictogram, messageType.Pictogram) == true) &&
                (this.Priority == messageType.Priority) &&
                (this.Procedure == messageType.Procedure);
        }

        return false;
    }

    public override int GetHashCode()
    {
        var result = this.Identification != null ? this.Identification.GetHashCode() : 0;
        result = (result * 397) ^ this.ActivateWindow.GetHashCode();
        result = (result * 397) ^ this.Logging.GetHashCode();
        result = (result * 397) ^ ((this.Pictogram != null) ? this.Pictogram.GetHashCode() : 0);
        result = (result * 397) ^ this.Priority.GetHashCode();
        result = (result * 397) ^ ((this.Procedure != null) ? this.Procedure.GetHashCode() : 0);
        return result;
    }

1 Answer 1

1

As far as I understand the question you should use Enumerable.SequenceEqual in Equals and some kind of aggregation within GetHashCode():

   byte[] extraData = ...

   ...

   public bool Equals(MessageType other) {
     ...

     if (!Enumerable.SequenceEqual(extraData, other.extraData))
       return false;

     ...  
   } 

   public override int GetHashCode() {
     unchecked { // we don't want IntegerOverflow exceptions to be thrown
       int result = ...

       ...  
       // let's combine hashes with xor
       result ^= extraData == null 
        ? 0
        : extraData.Aggerate(0, (s, a) => s ^ a); // ...and aggerate with xor as well

       ...

       return result;
     }
   }

In case extraData can be quite long (an appalling 1 GB for instance) you may want to restrict the computation to, say, 10 first items:

   result ^= extraData == null 
     ? 0
     : extraData.Take(10).Aggerate(0, (s, a) => s ^ a);
Sign up to request clarification or add additional context in comments.

2 Comments

what do you mean with? "// ...and aggerate with xor as well" would this simply do the trick: result = (result * 397) ^ ((this.Pictogram != null) ? this.Pictogram.Aggregate(0, (s, a) => s ^ a) : 0); ?
@Vincent Advocaat: there're many formulae you can use to combine hashes; result = (result * 397) ^ ... is OK as well and the trick does work; just not forget to wrap the entire GetHashCode into unchecked {...} (you don't want integer overflow exception to be thrown)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.