Implementing IEqualityComparer for custom object comparison

I had a simple snippet of code:


foreach (var muscle in muscles)
{
var currentMuscle = new ExerciseGroup(muscle.Name, muscle.Name);

var foundMuscles = from e in ModelExercises
where e.PrimaryMuscles.Contains(muscle)
select e;
currentMuscle.AddRange(foundMuscles);
GroupedExercises.Add(currentMuscle);
}

However where e.PrimaryMuscles.Contains(muscle) refused to generate any results. To me, it was logical that the muscles are the same (they Shared and ID and a Name), but to the compiler they were different. Obviously, they were equal in properties but not the same object… Silly me. So the problem is stated the stage is set.

Thankfully .Contains() has an overload that takes two parameters an object and an IEqualityComparer, great! Let’s get implementing!


private IEqualityComparer<Muscle> _compareMuscle { get; set; } = new MuscleComparer();

private class MuscleComparer : IEqualityComparer<Muscle>
{
public bool Equals(Muscle x, Muscle y)
{
bool id=false;
bool name=false;
if (x.Id == y.Id)
id = true;
if (x.Name == y.Name)
name = true;
return id && name;
}

public int GetHashCode(Muscle muscle)
{
int hCode = muscle.Id ^ muscle.Name.Length;
return hCode.GetHashCode();
}
}

So a very simple interface of two methods Equals and GetHashCode quick implementation and now our app returns a proper segmented view:

Perfect, it does, however, take a performance hit after this change (the load takes ~2seconds) so I might want to look at making it faster somehow.

Advertisements

3 thoughts on “Implementing IEqualityComparer for custom object comparison

  1. Maybe I’ll just share related trick that saves time when you need equality comparer and have ReSharper installed:
    ReSharper->Edit->Generate Code->Equality members (or Equality Comparer if we need it in a separate class).

    Usually much quicker than googling “best algorithm to implement GetHashCode” 😉

    Like

    • Hi Paweł thanks for the tip, while I am still mastering C# I try to stay away from 3rd party automations, just so I don’t become dependent. But sometimes we have bad ideas, do you think getting the hashcode can be optimized?

      Like

      • Hey! actually the one that is based on string’s length (as in example) is pretty weak, because it’s collisions will happen often. For example all the examples below will return the same hash code (equal “1”) when above function is used, even thought they are certainly pretty different:

        GetHashCode(new Muscle() { Id = 0, Name = “A” });
        GetHashCode(new Muscle() { Id = 1, Name = “” });
        GetHashCode(new Muscle() { Id = 2, Name = “BBB” });
        GetHashCode(new Muscle() { Id = 3, Name = “CC” });

        When such HashCode is used on big collections, there will certainly be a performance hit.
        Sorry for late answer! 🙂

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s