2

I have a little strange problem.
I use Visual Studio and I am developing a project with C#.
I have two custom classes "Attr" and "FD" and I use lists that includes their objects e.g.

List<Attr> attrList = new List<Attr>();
List<FD> fdList = new List<FD>(); 

So when I try to find the intersection of two lists the result is not what I expect. To make it more simple I tried to Intersect similar Objects and the result is wrong again. What is going wrong?

This is the fd. It is an object of class FD. this is the fd
This is the ff which is also an object of FD class. this is ff

As you can see these object contains exactly the same values.
The method GetLeft() returns a list that contains objects of class Attr.

So when I try to find the intersection between those two lists (fd.GetLeft() and ff.GetLeft() ) the result is nothing (it should be a list that contains an Attr object "A"). this is intersection

What did I miss?

P.S. These screenshots are from the debugg mode in Visual Studio.

Timitry
  • 2,646
  • 20
  • 26
Lefteris Xris
  • 900
  • 1
  • 11
  • 21
  • You have a custom class so what method are you using for EQUAL? See http://stackoverflow.com/questions/19583793/custom-intersect-in-lambda – jdweng Mar 30 '17 at 09:59

2 Answers2

3

In order to use Intersect I suggest implementing IEqualityComparer<T>, something like this :

public class FD
{
    public string Name { get; set; }
}

 static void Main()
    {
        List<FD> fdList1 = new List<FD>();
        fdList1.Add(new FD { Name = "a" });

        List<FD> fdList2 = new List<FD>();
        fdList2.Add(new FD { Name = "a" });

       IEnumerable<FD> fd = fdList1.Intersect<FD>(fdList2, new ComparerFd()).ToList();
    }

And the CamparerFd should be like this :

public class ComparerFd : IEqualityComparer<FD>
{

    public bool Equals(FD x, FD y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(FD obj)
    {
        if(obj == null) return 0;
        
        return obj.Name.GetHashCode();//Or whatever way to get hash code
    }
}
Ali Ezzat Odeh
  • 2,093
  • 1
  • 17
  • 17
  • Your implementation of `GetHashCode` is wrong, since just returning a random number does not return the same hash code for equal objects. Due to that, the `Intersect`-method will still not work, if it uses the hash code for fast comparisons (and I'd be pretty sure that it does). Generally, if not implementing `GetHashCode` correctly, It would be better to atleast return a constant value - this way, everything will work, and "only" be slow... In this specific case, just return `this.Name.GetHashCode()`. – Timitry Mar 30 '17 at 11:53
  • Thanks a lot both of you guys!! @Timitry. Problem solved! – Lefteris Xris Apr 02 '17 at 21:58
  • 1
    `this.Name` does not exist in the `ComparerFd` class. I think you meant `return obj.Name.GetHashCode();`. I have used this approach and it worked. Also note you should check for and handle null: `return obj.Name == null ? 0 : obj.Name.GetHashCode();` – SleekPanther Oct 15 '20 at 15:57
  • @SleekPanther thanks for the notes, updated in the answer :) – Ali Ezzat Odeh Oct 18 '20 at 06:08
2

If you created your own class, and did not override the Equals-method in that class, the Intersect-method will only compare the references of the objects, and not the properties.

Take the following, really simple class:

class MyClass
{
  int Value { get; set; }

  public MyClass(int value)
  {
    this.Value = value;
  }
}

Now, create two lists, with both containing one object. The properties of the objects are the same, but the instances are not:

  var list1 = new List<MyClass>
  {
    new MyClass(5)
  };

  var list2 = new List<MyClass>
  {
    new MyClass(5)
  };

So the following will happen:

  list1[0].Equals(list2[0]); // false
  list1.Intersect(list2); // No matches

If you want these methods to compare the properties of your MyClass-objects, implement IEqualityComparer<MyClass>, e.g. change the classes signature to:

class MyClass : IEqualityComparer<MyClass>
{
  ..
}

Alternatively, you can just override Equals and GetHashCode, as then these methods will be called as default IEqualityComparer.

See the this answer on how to properly override Equals and GetHashCode.

Graham
  • 7,431
  • 18
  • 59
  • 84
Timitry
  • 2,646
  • 20
  • 26