Как работает Func <T, TResult>? - PullRequest
19 голосов
/ 31 июля 2009

Я создаю метод расширения Distinct, в котором я могу передать критерии, подобные следующим.

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

Я получил код из Интернета, но мне трудно понять цель Func<T, TResult>. Кроме того, когда я говорю p => p.Name, отправляю ли я String Name или отправляю полный объект Person? Вот новый метод Distinct:

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

А вот использование:

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

Ответы [ 3 ]

34 голосов
/ 31 июля 2009

Когда вы делаете это:

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

Вы в основном создаете функцию на лету ( с использованием лямбда-выражений ), которая выглядит следующим образом:

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

Эта функция подходит для подписи делегата Func<Person,String>.Метод Distinct может принимать делегат (в основном указатель на функцию), который он использует для определения того, является ли элемент отдельным - в вашем случае, только уникальные строки (возвращаемые функцией выше) будут считаться «отличными» элементами.Этот делегат запускается для каждого перечисляемого элемента ваших «лиц», и используются результаты этих функций.Затем он создает последовательность (IEnumerable<Person>) из этих элементов.

8 голосов
/ 31 июля 2009
Func<T, TResult>

определяет функцию, которая принимает один параметр (типа T) и возвращает объект (типа TResult).

В вашем случае, если вам нужна функция, которая принимает объект Person и возвращает строку ... вам нужно

Func<Person, string>

, что эквивалентно:

string Function(Person p)
{
    return p.Name;
}
0 голосов
/ 31 июля 2009

Вы возвращаете разных людей, при условии, что два человека одинаковы, если у них одинаковое имя

Если вам нужен отдельный набор имен, вы можете использовать это:

IEnumerable<String> names = persons.Select(p => p.Name).Distinct();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...