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;
}
}
Jest to oparte na przykładzie w "LINQ w akcji". Listing 4.16.Wyraźne nie działa z LINQ do obiektów
To drukuje Jon Skeet dwa razy. Czemu? Próbowałem nawet przesłonić metodę Equals w klasie autora. Still Distinct nie działa. czego mi brakuje?
Edytuj: Dodałem też przeciążenie operatora == i! =. Nadal nie ma pomocy.
public static bool operator ==(Author a, Author b)
{
return true;
}
public static bool operator !=(Author a, Author b)
{
return false;
}
IEquatable jest w porządku, ale niekompletne; powinieneś * zawsze * wdrażać razem Object.Equals() i Object.GetHashCode(); IEquatable .Equals nie zastępuje Object.Equals, więc to się nie powiedzie podczas wykonywania porównań niesfornych, które występują często w frameworkach i zawsze w kolekcjach nie generycznych. –
AndyM
Więc lepiej jest użyć zastąpienia Distinct, które ma IEqualityComparer, jak zasugerował Rex M? Mam na myśli to, co powinienem robić, jeśli nie chcę wpaść w pułapkę. –
Tanmoy
@Tanmoy to zależy. Jeśli chcesz, aby autor normalnie zachowywał się jak normalny obiekt (to jest tylko referencyjna równość), ale sprawdzaj wartości nazw dla celu Distinct, użyj IEqualityComparer. Jeśli * zawsze * chcesz, aby obiekty Autora były porównywane na podstawie wartości nazw, to nadpisuj GetHashCode i Equals lub implementuj IEquatable. –