class Program { static void Main(string[] args) { List<Book> books = new List<Book> { new Book { Name="C# in Depth", Authors = new List<Author> { new Author { FirstName = "Jon", LastName="Skeet" }, new Author { FirstName = "Jon", LastName="Skeet" }, } }, new Book { Name="LINQ in Action", Authors = new List<Author> { new Author { FirstName = "Fabrice", LastName="Marguerie" }, new Author { FirstName = "Steve", LastName="Eichert" }, new Author { FirstName = "Jim", LastName="Wooley" }, } }, }; var temp = books.SelectMany(book => book.Authors).Distinct(); foreach (var author in temp) { Console.WriteLine(author.FirstName + " " + author.LastName); } Console.Read(); } } public class Book { public string Name { get; set; } public List<Author> Authors { get; set; } } public class Author { public string FirstName { get; set; } public string LastName { get; set; } public override bool Equals(object obj) { return true; //if (obj.GetType() != typeof(Author)) return false; //else return ((Author)obj).FirstName == this.FirstName && ((Author)obj).FirstName == this.LastName; } }
This is based on an example in "LINQ in Action". Listing 4.16.
This prints Jon Skeet twice. Why? I have even tried overriding Equals method in Author class. Still Distinct does not seem to work. What am I missing?
Edit: I have added == and != operator overload too. Still no help.
public static bool operator ==(Author a, Author b) { return true; } public static bool operator !=(Author a, Author b) { return false; }
LINQ Distinct is not that smart when it comes to custom objects. All it does is look at your list and see that it has two different objects (it doesn't care that they have the same values for the member fields). One workaround is to implement the IEquatable interface as shown here.
LINQ Distinct operator removes all the duplicate values from the collection and finally returns the dissimilar or unique values. The LINQ Distinct operator available in only Method Syntax and it not supports the Query Syntax. LINQ Distinct is an operator which comes under Set Operator.
c# - Linq distinct doesn't call Equals method - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.
LINQ Distinct is not that smart when it comes to custom objects.
All it does is look at your list and see that it has two different objects (it doesn't care that they have the same values for the member fields).
One workaround is to implement the IEquatable interface as shown here.
If you modify your Author class like so it should work.
public class Author : IEquatable<Author> { public string FirstName { get; set; } public string LastName { 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; } }
Try it as DotNetFiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With