Error in ServiceKey.Equals

Developer
Apr 15, 2009 at 8:19 PM
Kzu,
You are comparing the hashcodes to determine equality.  Unfortunately, multiple ServiceKeys can generate the same hashcode.

Typically the hashcode is used in HashTable (such as in Dictionary<>) to subdivide entries into buckets that are then search using Equals.

With the current implementation you would always return the first item in the bucket for the hashcode.  Take a look at what I did in Munq 

 

internal class RegistrationKey<TType> : IRegistrationKey where TType : class
{
    
public override bool Equals(object obj)
    {
        return obj is RegistrationKey<TType>;
    }

 

 

    public override int GetHashCode()
    {
        
return typeof(TType).GetHashCode();
    }
}

 

 

internal class NamedRegistrationKey<TType> : IRegistrationKey where TType : class
{
    
private string name;

 

 

    public NamedRegistrationKey(string name)
    {
        
this.name = name;
    }

 

 

    public override bool Equals(object obj)
    {
        
var other = obj as NamedRegistrationKey<TType>;
        
return (other != null) && (this.name == other.name);
    }

 

 

    public override int GetHashCode()
    {
        
return typeof(TType).GetHashCode();
    }
}

 

Coordinator
Apr 17, 2009 at 1:19 AM
You got me!

Fixed and checked-in :)
Developer
Apr 18, 2009 at 6:12 PM
Kzu,
You still have the obj1.hash != obj2.hash in the Equals.  This is redundant.  The dictionary's hashtable uses the hash to find the correct bucket and then equality comparisions to find the right entry.

Also, do the comparison for factory type first.  It is most likely different and the && will terminate without doing the name comparison.
Coordinator
Jun 19, 2009 at 6:23 PM
Doing factory type or name first would be the same imo

-original message-
Subject: Re: Error in ServiceKey.Equals [funq:53415]
From: mdennis <[email removed]>
Date: 18/04/2009 3:12 pm

From: mdennis

Kzu,
You still have the obj1.hash != obj2.hash in the Equals. This is redundant. The dictionary's hashtable uses the hash to find the correct bucket and then equality comparisions to find the right entry.

Also, do the comparison for factory type first. It is most likely different and the && will terminate without doing the name comparison.

Developer
Jun 19, 2009 at 8:02 PM

actually, you are likely to have many registrations with no name, while few for the same type.  This if the name comparision is done first the

obj1.name != obj2.name && obj1.objectType != obj2.objectType

will terminate faster on average and not execute the type comparision.

 

Matthew