Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.net IEnumerable Except with custom IEqualityComparer not working as expected

Tags:

c#

.net

linq

I am currently a bit confused with the IEnumerable.Except() Method. I tried to perform set operations build on the data id of Objects. So, I wrote a custom Equality Comparer. But the result is totally not what I expected. The example:

class Program
{
    static void Main(string[] args)
    {
        List<int> IntList1 = new List<int> { 42, 43 };
        List<int> IntList2 = new List<int> { 42 };

        var intResultList = IntList1.Except(IntList2).ToList();
        intResultList.ForEach(s => Console.WriteLine(s));

        List<DataStructure> List1 = new List<DataStructure> { new DataStructure { DataID = 42, SomeText = "42" }, new DataStructure {DataID = 43, SomeText = "43"} };
        List<DataStructure> List2 = new List<DataStructure> { new DataStructure { DataID = 42, SomeText = "42" }};

        var comparer = new DataStructureComparer();

        var resultList = List1.Except(List2, comparer).ToList();

        resultList.ForEach(s => Console.WriteLine(s.SomeText));

        Console.ReadLine();
    }
}

public class DataStructureComparer: IEqualityComparer<DataStructure>
{

    public bool Equals(DataStructure x, DataStructure y)
    {
        return x.DataID == y.DataID;
    }

    public int GetHashCode(DataStructure obj)
    {
        return obj.GetHashCode();
    }
}

public class DataStructure
{
    public int DataID;
    public string SomeText;
}

The Output goes like this: 43 42 43

But I would have expected it to be 43 43

Why is my assumption wrong?

brgds Sven Weiberg

like image 295
Sven Weiberg Avatar asked Mar 11 '23 00:03

Sven Weiberg


1 Answers

The reason for this is your implementation of GetHashCode(). It gives different hashcodes for all your DataStructure instances.

Change it to something like:

public int GetHashCode(DataStructure obj)
{
    return obj.DataID;
}

To increase performance, Except will at first compare the hash codes of the objects. Only if they are equal it will call Equals to determine if the objects are really equal in your meaning of equal.

Different hashes tell it that the objects are not equal. And you use the base implementation of object.GetHashCode() which will mostly give different values for different instances.

Since your equality is determined by the DataID property, it makes sense to use this value as hash code, too.

like image 144
René Vogt Avatar answered Mar 13 '23 06:03

René Vogt