2012-11-11 23 views
11

Czytałem książkę o Linq i zauważyłem, że metoda Distinct ma przeciążenie, które wymaga porównania. Byłoby to dobrym rozwiązaniem problemu, który mam, gdy chcę uzyskać oddzielne elementy z kolekcji, ale chcę, aby porównanie było na identyfikatorze jednostki, nawet jeśli inne właściwości są różne.Jak używać niestandardowego porównywalnika z metodą Linq Distinct?

Według książki, jeśli mam podmiot Gribulator, byłbym w stanie stworzyć porównywarka takiego ...

private class GribulatorComparer : IComparer<Gribulator> { 
    public int Compare(Gribulator g1, Gribulator g2) { 
    return g1.ID.CompareTo(g2.ID); 
    } 
} 

... a następnie używać go tak ...

List<Gribulator> distinctGribulators 
    = myGribulators.Distinct(new GribulatorComparer()).ToList(); 

to jednak daje następujące błędy kompilatora ...

„System.Collections.Generic.List” nie zawierają definicji dla „różne”, a najlepszą metodą przeciążeniem przedłużacza „System.Linq.Enumerable .Distinct (System.Collections.Generic.IEnumerable, System.Collections.Generic.IEqualityComparer) 'ma pewne nieprawidłowe argumenty

Argument 2: nie można przekonwertować z 'LinqPlayground.Program.GribulatorComparer' do' System.Collections.Generic.IEqualityComparer "

Szukałem trochę i widziałem wiele przykładów, które wykorzystują kod taki jak ten, ale nie ma żadnych skarg na błędy kompilatora.

Co robię źle? Czy jest to najlepszy sposób na zrobienie tego? Chcę tutaj jednorazowego rozwiązania, więc nie chcę zaczynać zmieniać kodu dla samej jednostki. Chcę, by byt pozostał jak zwykle, ale tylko w tym jednym miejscu, porównaj tylko przez ID.

Dzięki za pomoc.

+0

Zapomniałem dodać, używam VS2012, a więc .NET 4.0 w C# –

Odpowiedz

13

Ty realizacji Twojego porównywarka jako IComparer<T> metoda przeciążenie LINQ wymaga wdrożenia IEqualityComparer:

private class GribulatorComparer : IEqualityComparer<Gribulator> { 
    public bool Equals(Gribulator g1, Gribulator g2) { 
    return g1.ID == g2.ID; 
    } 
} 

edit:

Dla wyjaśnienia, interfejs IComparer można wykorzystać do sortowania, jak w zasadzie to robi metoda Compare().

Jak to:

items.OrderBy(x => new ItemComparer()); 

private class ItemComparer : IComparer<Item> 
{ 
    public int Compare(Item x, Item y) 
    { 
     return x.Id.CompareTo(y.Id) 
    } 
} 

Które uporządkować swoją kolekcję przy użyciu tego porównywarka jednak LINQ to sposób, aby to zrobić dla prostych dziedzin (takich jak int Id).

items.OrderBy(x => x.Id); 
+0

Dzięki Peter, to wyjaśnia! Przykład, którego użyłem w książce, był dla OrderBy, ale odniósł się do tego z miejsca, w którym omawiał Distinct, i nie zauważyłem, że potrzebuję innego interfejsu. W książce nie było to zbyt jasne :( –

+0

Przy okazji, czy wiesz, że istnieje sposób, aby to zrobić z anonimową funkcją, zamiast tworzyć oddzielną klasę dla porównywalnika? Wydaje się, że przesada –

+0

jak wiem, nie ma, tak naprawdę zastanawiałem się nad przeciążeniem operatorów linq takimi rzeczami: –