2009-07-31 17 views
19

Sto creando un metodo di estensione Distinta in cui posso passare i criteri come il seguente.Come funziona Func <T,TResult>?

persons.Distinct(p => p.Name); 

ho ottenuto il codice dal web, ma sto avendo difficoltà a capire lo scopo della Func<T, TResult>. Inoltre, quando dico p => p.Name sto inviando il StringName o sto inviando l'oggetto completo Person? Ecco il nuovo metodo distinte:

public static class ExtensionMethods 
{ 
    public static IEnumerable<T> Distinct<T>(
     this IEnumerable<T> list, Func<T,object> checker) 
    { 
     return list.Distinct(new GenericComparer<T>(checker)); 
    } 
} 

public class GenericComparer<T> : IEqualityComparer<T> 
{ 
    private Func<T, object> _checker; 

    public GenericComparer(Func<T,object> checker) 
    { 
     _checker = checker; 
    } 

    public bool Equals(T x, T y) 
    { 
     return _checker(x).Equals(_checker(y)); 
    } 

    public int GetHashCode(T obj) 
    { 
     return _checker(obj).GetHashCode(); 
    } 
} 

E qui è l'utilizzo:

static void Main(string[] args) 
{ 
    var persons = new List<Person>() 
    { 
     new Person() { Id = 1, Name = "Mary"}, 
     new Person() {Id = 2, Name="John"}, 
     new Person() { Id = 3, Name = "Mary"} 
    }; 

    var uniquePersons = persons.Distinct(p => p.Name); 

    foreach(var person in uniquePersons) 
    { 
     Console.WriteLine(person.Name); 
    } 
} 

risposta

34

Quando si esegue questa operazione:

persons.Distinct(p => p.Name); 

Stai fondamentalmente creazione di una funzione al volo (using lambda expressions), che assomiglia a questo:

string theFunction(Person p) 
{ 
    return p.Name; 
} 

Questa è una funzione che si adatta alla firma di un delegato Func<Person,String>. Il metodo Distinct può assumere un delegato (fondamentalmente un puntatore a funzione) che utilizza per determinare se un elemento è diverso o meno; nel tuo caso, solo le stringhe univoche (restituite dalla funzione precedente) saranno considerate elementi "distinti". Questo delegato viene eseguito su ciascun elemento delle "persone" enumerabili e vengono utilizzati i risultati di tali funzioni. Quindi crea una sequenza (IEnumerable<Person>) da quegli elementi.

+0

+1, ma "Nel tuo caso, un elemento è distinto se nessun altro elemento ha lo stesso' Nome'. Se più di un elemento nella sorgente ha lo stesso nome, solo il primo di essi sarà presente nel risultato. "Inoltre, nessun sovraccarico del metodo' Distict() 'prende un selettore - hai scritto il tuo? –

+0

il La domanda OP mostra come viene definita l'estensione Distinct ... – ShuggyCoUk

+0

Sì, ho ottenuto un metodo di estensione Distinto di Internet! Non l'ho scritto io stesso! –

8
Func<T, TResult> 

definisce una funzione che accetta un parametro (di tipo T) e restituisce un oggetto (di tipo TResult).

Nel tuo caso, se si desidera una funzione che prende un oggetto Person e restituisce una stringa ... che ci si vuole

Func<Person, string> 

che è l'equivalente di:

string Function(Person p) 
{ 
    return p.Name; 
} 
0

È stanno tornando le persone distinte, nel presupposto che due persone sono uguali se hanno lo stesso nome

Se si desidera un insieme distinto di nomi, è possibile utilizzare questo:

IEnumerable<String> names = persons.Select(p => p.Name).Distinct(); 
Problemi correlati