Подтвердить что ты не робот

Как работает Func <T, TResult>?

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

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

Я получил код из Интернета, но мне трудно понять цель Func<T, TResult>. Кроме того, когда я говорю p => p.Name am, я отправляю 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);
    }
}
4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

Func<T, TResult>

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

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

Func<Person, string>

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

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

Ответ 3

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

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

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