In order for the LINQ Distinct operator to function correctly in a multi-field comparison,
we must provide it with a custom implementation that allows it to truly return
what we define as "distinct". Otherwise, it may fail to work.
In order to implement IEquatable in a class, we need only the Equals and to override
the GetHashCode methods. Equals in the example compares both the first and last
names and returns true for a match and false otherwise. GetHashCode similarly
returns a unique hash value based on the fact that both the first and last name properties of the class are what make an instance "distinct".
Here is a sample Author class that properly implements IEquatable:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace QuotationLib
{
public class Author : IEquatable<Author>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string AuthorInfo { get; set; }
public bool Equals(Author other)
{
if (FirstName == other.FirstName && LastName == other.LastName) return true;
return false;
}
public override int GetHashCode()
{
int hashFirstName = FirstName == null ? 0 : FirstName.GetHashCode();
int hashLastName = LastName == null ? 0 : LastName.GetHashCode();
return hashFirstName ^ hashLastName;
}
}
}
With the Equals and the GetHashCode methods in place, we can now issue a query like
this:
public static List<Author> GetAuthors()
{
var Authors = (
from q in Quotes
select
new Author()
{
AuthorInfo = q.AuthorInfo,
FirstName = q.AuthorFirstName,
LastName = q.AuthorLastName
}).Distinct().ToList();
return Authors;
}
The above will now return a true "distinct" list of our authors.Without
this, Distinct wouldn't know what to do and you would still get all Authors in
the collection.