Как работает 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);
}
}
Ответы
Ответ 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();