2012-11-11 12 views
11

Stavo leggendo un libro su Linq e ho visto che il metodo Distinct ha un sovraccarico che richiede un confronto. Questa sarebbe una buona soluzione per un problema che ho dove voglio ottenere le entità distinte da una raccolta, ma voglio che il confronto sia sull'ID entità, anche se le altre proprietà sono diverse.Come si utilizza un confronto personalizzato con il metodo Distinct di Linq?

Secondo il libro, se ho un'entità Gribulator, dovrei essere in grado di creare un operatore di confronto come questo ...

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

... e poi usarlo come questo ...

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

Tuttavia, questo dà i seguenti errori del compilatore ...

'System.Collections.Generic.List' non contiene una definizione per 'distinto' e il miglior metodo di overload estensione 'System.Linq.Enumerable .Distinct (System.Collections.Generic.IEnumerable, System.Collections.Generic.IEqualityComparer) 'ha alcuni argomenti non validi

Argomento 2: non è possibile convertire da 'LinqPlayground.Program.GribulatorComparer' a' System.Collections.Generic.IEqualityComparer '

Ho cercato un po' e ho visto un sacco di esempi che usano un codice come questo, ma non ho lamentele sugli errori del compilatore.

Cosa sto sbagliando? Inoltre, è questo il modo migliore per farlo? Voglio una soluzione una tantum qui, quindi non voglio iniziare a cambiare il codice per l'entità stessa. Voglio che l'entità rimanga normale, ma solo in questo posto, confronta solo per ID.

Grazie per qualsiasi aiuto.

+0

dimenticato di aggiungere, sto usando VS2012, e così NET 4.0 in C# –

risposta

13

Stai implementare il confronto di come IComparer<T>, il metodo di overload LINQ richiede un'implementazione di IEqualityComparer:

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

edit:

Per chiarimenti, l'interfaccia IComparer può essere utilizzato per l'ordinamento, come questo è fondamentalmente ciò che fa il metodo Compare().

Ti piace questa:

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

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

Quale sarà ordinare la vostra collezione usando che di confronto, tuttavia LINQ offre un modo di fare che per i campi semplici (come un int Id).

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

Grazie Peter, che spiega tutto! L'esempio che stavo usando nel libro era per OrderBy, ma ci aveva fatto riferimento da dove parlava di Distinct, e non avevo capito che avevo bisogno di un'interfaccia diversa. Non era molto chiaro nel libro in realtà :( –

+0

A proposito, sai se c'è un modo per farlo con una funzione anonima, invece di dover creare una classe separata per il confronto? Sembra eccessivo. –

+0

Per quanto riguarda come so, non c'è, ho pensato davvero di sovraccaricare gli operatori di linq con cose del genere –

Problemi correlati