I have the following code
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
List<I> bars = new List<I>();
bars.Add(new A() { Id = 1 });
bars.Add(new B() { Id = 1 });
bars.Add(new A() { Id = 1 });
var distictBars = bars.Distinct();
foreach (var item in distictBars)
{
Debug.WriteLine(item.Name);
}
}
}
interface I
{
string Name { get; }
}
class Base
{
public int Id { get; set; }
}
class A : Base, I, IEquatable<A>
{
public string Name
{
get { return this.Id + "-A"; }
}
public bool Equals(A other)
{
return this.Id == other.Id;
}
public override bool Equals(object obj)
{
if (obj is A)
return this.Equals(obj as A);
else
return object.ReferenceEquals(this, obj);
}
}
class B : Base, I, IEquatable<B>
{
public string Name
{
get { return this.Id + "-B"; }
}
public bool Equals(B other)
{
return this.Id == other.Id;
}
public override bool Equals(object obj)
{
if (obj is A)
return this.Equals(obj as A);
else
return object.ReferenceEquals(this, obj);
}
}
}
The output is the following
1-A
1-B
1-A
I need however the following
1-A
1-B
that is, eliminate the duplicates of type A or B. It seems that the Distinct LINQ method didn’t take in consideration my Equals override, nor the IEquitable interface implementation.
How should I proceed in order than that method does the specified comparison?
The
Distinctmethod will likely use something similar to aHashSet<T>internally, which relies on a hash code (obviously). You will need to also overrideGetHashCode.It seems to me you have some unnecessary duplication in general. Both your
AandBclasses share basically the same logic for determining equality; is what you want to ensure that twoBaseobjects are equal if their IDs are equal and they are the same type? (This is what it looks like to me; your implementation seems to contain a couple of mistakes in this case, but that’s still my best guess.)If so, just make
BaseimplementIEquatable<Base>and yourAandBimplementations become much simpler:Notice that I also changed the setter on the
Idproperty toprivate; in general, it’s a very risky game to make a field or property publicly writable when it’s used in the type’sGetHashCodeimplementation (since if an object’s hash code ever changes, it stops working as a key in a hashtable).This comment becomes unnecessary if you apply my recommendation above.
Also, warning! It looks to me like you’ve got a risk of infinite recursion in your
B.Equalsmethod: