1

I have the following simple object:

public class Net : IEqualityComparer<Net>
{
    public string Name { get; private set; }
    public int Id { get; set; }

    private Gate _inGate;
    private Gate _outGate;
    private NetValue _value = NetValue.NotSet;
    private bool _isMiddleNet;

    //constructor and stuff!!!.....

    //Equality comparer
    public bool Equals(Net x, Net y)
    {
        return (x.Id == y.Id && x.Name == y.Name);
    }

    public int GetHashCode(Net obj)
    {
        return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
    }

    public override int GetHashCode()
    {
        return 13 * Id.GetHashCode() + 7 * Name.GetHashCode();
    }

So basically I am interested to say 2 instance of this object are equal if and only if their Id and Name members are equal...

But somewhere else in another class I have to List<Net> and I want to perform distinction on these lists:

    inputNetsA = inputNetsA.Distinct().ToList();
    inputNetsB = inputNetsB.Distinct().ToList();

But this does not work what so ever! What am I doing wrong?

Dumbo
  • 13,555
  • 54
  • 184
  • 288
  • 1
    Side q: why 2 implementations of GetHashCode are so different in your sample? And where is `object.Equals` implementation? See http://stackoverflow.com/questions/4095395/whats-the-role-of-gethashcode-in-the-iequalitycomparert-in-net and linked questions for info... – Alexei Levenkov Jun 30 '15 at 05:10

1 Answers1

3

You need to make the objects IEquatable<T>. The IEqualityComparer<T> is an interface for objects that compares two objects with eachother. The IEquatable<T> is used for comparing an object with another object of the same type.

Otherwise, if you wanted to use IEqualityComparer<T>, it's meant to be passed in to the Distinct() method.

// better to extend off of EqualityComparer<T> instead of
//     implementing IEqualityComparer<T> directly
public class NetComparer : EqualityComparer<Net>
{
    public override bool Equals(Net x, Net y)
    {
        return (x.Id == y.Id && x.Name == y.Name);
    }

    public override int GetHashCode(Net obj)
    {
        return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
    }
}

inputNetsA = inputNetsA.Distinct(new NetComparer()).ToList();
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
  • Thanks a lot. I get NullReference on this line `return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();` – Dumbo Jun 30 '15 at 04:26
  • Is it ok if I just return null in GetHashCode? – Dumbo Jun 30 '15 at 04:47
  • The return type of `GetHashCode()` is `int`, you can't return `null`. All I can really say about that is, return whatever is appropriate for that type. If one of the members of the object that is used to generate a hash code can be `null`, then maybe it's not a suitable key? Otherwise, you need to decide on a way to deal with them. e.g., treat them as `0` – Jeff Mercado Jun 30 '15 at 04:50
  • What is the advantage of *better to extend off of `EqualityComparer` instead of implementing `IEqualityComparer` directly*? I haven't ever heard of it, and in the end the interface has two methods, and the `EqualityComparer` has two abstract methods (that are the same)... – xanatos Jun 30 '15 at 07:16
  • @JeffMercado Ignore it... Seen your other response... http://stackoverflow.com/a/5707968/613130 . The class implements the non-generic versions by calling the generic (overloadable) version. – xanatos Jun 30 '15 at 07:26