Reputation: 1886
I created class with overriden Equals. The problem is that Distinct method doesn't work for my class.
class MyClass
{
public int Item1 { get; private set; }
public int Item2 { get; private set; }
public MyClass(int item1, int item2)=>(Item1,Item2)=(item1,item2);
public override bool Equals(object obj)
{
var other = obj as MyClass;
if (other == null)
{
return false;
}
return (this.Item1 == other.Item1 && this.Item2 == other.Item2);
}
}
class Program
{
static void Main(string[] args)
{
MyClass x = new MyClass(1, 0);
MyClass y = new MyClass(1, 0);
var list = new List<MyClass>();
list.Add(x);
list.Add(y);
bool b = x.Equals(y)); //True
var distincts = list.Distinct(); //Doesn't work, contains both
}
}
How can I fix that and why it doesn't use my Equals in Distinct?
Upvotes: 2
Views: 929
Reputation: 13652
You have to override GetHashCode
as well:
public override int GetHashCode()
{
return Item1; // or something
}
Distinct
first compares the hashcodes, which should be computed faster than the actual Equals
. Equals
is only further evaulated if the hashcodes are equal for two instances.
Upvotes: 2
Reputation: 271735
Distinct
docs:
Returns distinct elements from a sequence by using the default equality comparer to compare values.
Let's see what the default equality comparer does:
The
Default
property checks whether type T implements theSystem.IEquatable<T>
interface and, if so, returns anEqualityComparer<T>
that uses that implementation. Otherwise, it returns anEqualityComparer<T>
that uses the overrides ofObject.Equals
andObject.GetHashCode
provided by T.
So basically, to make this work, you either:
GetHashCode
as wellIEquatable<T>
Distinct
that accepts a custom equality comparer.If I were you, I would choose the second one because you need to change the least of your code.
class MyClass: IEquatable<MyClass> {
...
public bool Equals(MyClass obj)
{
if (obj == null)
{
return false;
}
return (this.Item1 == obj.Item1 && this.Item2 == obj.Item2);
}
}
Upvotes: 3
Reputation: 6766
You need to implement IEquatable<MyClass>
in MyClass
and provide your own implementation of GetHashCode
and Equals
method.
see this for more information.
class MyClass
{
public int Item1 { get; private set; }
public int Item2 { get; private set; }
public MyClass(int item1, int item2)=>(Item1,Item2)=(item1,item2);
public override bool Equals(object obj)
{
var other = obj as MyClass;
if (other == null)
{
return false;
}
return (this.Item1 == other.Item1 && this.Item2 == other.Item2);
}
public override int GetHashCode()
{
return this.Item1;
}
}
Upvotes: 1