2009-07-31 18 views
19

Tworzę metodę Distinct extension, w której mogę spełnić następujące kryteria.Jak działa Func <T,TResult>?

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

mam kod z sieci, ale mam trudności ze zrozumieniem cel Func<T, TResult>. Ponadto, gdy mówię: p => p.Name, wysyłam StringName lub czy wysyłam cały obiekt Person? Oto nowa metoda Wyraźny:

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(); 
    } 
} 

I tu jest użycie:

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); 
    } 
} 

Odpowiedz

34

Kiedy to zrobić:

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

jesteś w zasadzie tworzenia funkcji w locie (using lambda expressions), który wygląda tak:

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

Ta funkcja pasuje do podpisu delegata Func<Person,String>. Metoda Distinct może przyjmować delegata (w zasadzie wskaźnik funkcji), którego używa do określenia, czy element jest odrębny - w twoim przypadku tylko unikatowe ciągi (zwracane przez powyższą funkcję) będą uważane za "odrębne" elementy. Ten delegat jest uruchamiany na każdym elemencie twoich "osób", a wyniki tych funkcji są używane. Następnie tworzy sekwencję (IEnumerable<Person>) z tych elementów.

+0

+1, ale "W twoim przypadku element jest inny, jeśli żaden inny element nie ma tego samego" Nazwa ". Jeśli więcej niż jeden element w źródle ma taką samą nazwę, tylko pierwszy z nich będzie obecny w wyniku. "Ponadto, żadne przeciążenie metody' Distict() 'nie bierze selektora - czy napisałeś własny? –

+0

Pytanie OP pokazuje, jak zdefiniowano Distinct rozszerzenie ... – ShuggyCoUk

+0

Tak, mam Distinct rozszerzenie metody Internetu! Nie napisałem go samodzielnie! –

8
Func<T, TResult> 

definiuje funkcję, która przyjmuje jeden parametr (typu T) i zwraca obiekt (typu TResult).

w przypadku, jeśli chcesz funkcję, która pobiera obiekt Person i zwraca ciąg ... czego chcesz

Func<Person, string> 

który jest odpowiednikiem:

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

Ty wracają do różnych osób, przyjmując założenie, że dwoje ludzi jest takich samych, jeśli mają taką samą nazwę:

Jeśli chcesz mieć odrębny zestaw nazw, możesz użyć tego:

IEnumerable<String> names = persons.Select(p => p.Name).Distinct(); 
Powiązane problemy