I have the following EF class derived from a database (simplified)
class Product
{
public string ProductId;
public string Product
Answering the headline of the question (what attracted people here) and ignoring that the example used anonymous types....
This solution will also work for non-anonymous types. It should not be needed for anonymous types.
Helper class:
///
/// Allow IEqualityComparer to be configured within a lambda expression.
/// From https://stackoverflow.com/questions/98033/wrap-a-delegate-in-an-iequalitycomparer
///
///
public class LambdaEqualityComparer : IEqualityComparer
{
readonly Func _comparer;
readonly Func _hash;
///
/// Simplest constructor, provide a conversion to string for type T to use as a comparison key (GetHashCode() and Equals().
/// https://stackoverflow.com/questions/98033/wrap-a-delegate-in-an-iequalitycomparer, user "orip"
///
///
public LambdaEqualityComparer(Func toString)
: this((t1, t2) => toString(t1) == toString(t2), t => toString(t).GetHashCode())
{
}
///
/// Constructor. Assumes T.GetHashCode() is accurate.
///
///
public LambdaEqualityComparer(Func comparer)
: this(comparer, t => t.GetHashCode())
{
}
///
/// Constructor, provide a equality comparer and a hash.
///
///
///
public LambdaEqualityComparer(Func comparer, Func hash)
{
_comparer = comparer;
_hash = hash;
}
public bool Equals(T x, T y)
{
return _comparer(x, y);
}
public int GetHashCode(T obj)
{
return _hash(obj);
}
}
Simplest usage:
List products = duplicatedProducts.Distinct(
new LambdaEqualityComparer(p =>
String.Format("{0}{1}{2}{3}",
p.ProductId,
p.ProductName,
p.CategoryId,
p.CategoryName))
).ToList();
The simplest (but not that efficient) usage is to map to a string representation so that custom hashing is avoided. Equal strings already have equal hash codes.
Reference:
Wrap a delegate in an IEqualityComparer