views:

278

answers:

1

I'm trying to do a Linq GroupBy on some objects using an explicit key type. I'm not passing an IEqualityComparer to the GroupBy, so according to the docs:

The default equality comparer Default is used to compare keys.

It explains the EqualityComparer<T>.Default property like this:

The Default property checks whether type T implements the System.IEquatable<T> generic interface and if so returns an EqualityComparer<T> that uses that implementation.

In the code below, I'm grouping an array of Fred objects. They have a key type called FredKey, which implements IEquatable<FredKey>.

That should be enough to make the grouping work, but the grouping is not working. In the last line below I should have 2 groups, but I don't, I just have 3 groups containing the 3 input items.

Why is the grouping not working?

class Fred
{
    public string A;
    public string B;
    public FredKey Key
    {
        get { return new FredKey() { A = this.A }; }
    }
}

class FredKey : IEquatable<FredKey>
{
    public string A;
    public bool Equals(FredKey other)
    {
        return A == other.A;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var f = new Fred[]
        {
            new Fred {A = "hello", B = "frog"},
            new Fred {A = "jim", B = "jog"},
            new Fred {A = "hello", B = "bog"},
        };

        var groups = f.GroupBy(x => x.Key);
        Debug.Assert(groups.Count() == 2);  // <--- fails
    }
}
+1  A: 

From MSDN

If you implement IEquatable, you should also override the base class implementations of Object::Equals(Object) and GetHashCode() so that their behavior is consistent with that of the IEquatable::Equals method. If you do override Object::Equals(Object), your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class. This ensures that all invocations of the Equals() method return consistent results.

add this to FredKey and it should work

public override int GetHashCode()
    {
        return A.GetHashCode();
    }
Neil
That was it. Thanks. I found a good explanation here: http://www.codeproject.com/KB/dotnet/IEquatable.aspx
dangph