I'm trying to find a distinct List<Author>
given a List<BlogPost>
where each BlogPost
has an Author
property. I've found the Distinct()
extension method in generics and I'm trying to use it. First, let me explain my loop and where I want to use it, then I'll explain my classes and where I'm having trouble.
Trying to use distinct here
public List<Author> GetAuthors() {
List<BlogPost> posts = GetBlogPosts();
var authors = new List<Author>();
foreach (var bp in posts) {
authors.Add(bp.Author);
}
return authors.Distinct().ToList();
}
Based on what I've read on MSDN, Distinct()
either uses the default comparer or a passed in comparer. I was hoping (I obviosuly don't know if this is doable) to write a comparer in one spot and be able to use it for all of my classes since they all compare by the exact same equality operation (which compares the GUID
property of each class).
All of my classes inherit from the BasePage
class:
public class BasePage : System.Web.UI.Page, IBaseTemplate, IEquatable<IBaseTemplate>, IEqualityComparer<IBaseTemplate>
public class Author : BasePage
public class BlogPost : BasePage
My equals method implemented in BasePage
compares the GUID
property which is unique to each. When I call Distinct()
on an Author
it doesn't seem to work. Is there any way I can wrap up the comparer in one place and always be able to use it rather than having to write something like class AuhorComparer : IEqualityComparer<Auhor>
since I'd then need to write the same thing for each class, every time I want to use Distinct()
. Or can I override the default comparer somehow so I don't have to pass anything to Distinct()
?
The Distinct
operation is probably not the best solution here because you end up building a potentially very big list with duplicates only to then immediately shrink it to distinct elements. It's probably better to just start with a HashSet<Author>
to avoid building up the large list.
public List<Author> GetAuthors() {
HashSet<Author> authorSet = new HashSet<Author>();
foreach (var author in GetBlogPosts().Select(x => x.Author)) {
authorSet.Add(author);
}
return authorSet.ToList();
}
If you do want to use Distinct
then the best route is to implement IEquatable
on the Author
type. When not given an explicit IEqualityComparer
the Distinct
and other LINQ methods will eventually default into using the IEquatable
implementation on the type. Usually through EqualityComprare<T>.Default