Читать ответ как:
Группа userposts по UserId; для каждой группы, возьмите все посты для этого id; теперь для каждой группы, возьмите userId и все его сообщения и сделайте ... с ними.
Объяснение
Выражение f => f.UserId
, posts => posts
выглядят, как будто они функция. Но это не так. Ну, они есть, но вроде не ... ну, это сбивает с толку. То, что они делают, заполняется для некоторого синтаксиса, который не может существовать на языке C#.
Дело в том, как вы можете связаться с GroupBy()
способом:
- Что вы хотите сгруппировать по: ключевой
- То, что вы хотите иметь в каждой группе: Элементы
- Что (если таковые имеются) дальнейшей обработки, которую вы хотите сделать с элементами в каждой группе. (Это третья пуля является хорошим бы иметь, но это то, что основа дает нам)
Было бы хорошо, если бы C# может поддерживать следующий синтаксис:
var groupedPosts = userposts.GroupBy(UserId, this, (k, v) => {...});
но вы можете сразу увидеть которые никогда не скомпилировались. Вы должны объяснить компилятору, что UserId
означает свойство UserPost
этого имени и что this
в свою очередь относится к каждому пользовательскому адресу. Перед дженериков & лямбды, .net часто решаются такого рода вещи с помощью строки для имя_поля:
var groupedPosts = userposts.GroupBy("UserId", "", (k, v) => {...});
, а затем там должен быть какой-то во время выполнения отражения, чтобы превратить эту строку в PROPERTYNAME & затем получить значение, & понимать, что "" означает все UserPost
Но в C# мы любим строго типизировать. И лямбда дает симпатичный но-не-сразу-очевидный способ «имя» свойство в сильном типизированного образом:
f=> f.UserId
вы видите? Прочитайте это не так много, как функции, но, как именование свойство: «Я хочу UserId каждого userpost»
Аналогично, вы можете «имя» в единое целое:
f => f // means exactly the same as posts=>posts
(Функция x=>x
является называемой тождественной функцией в информатике). И поэтому трудно «визуализировать» делегата. Лямбда используется в качестве аккуратного, точного определения типа поля или свойства .
[Если это кристально чисто, позвольте мне теперь отменить инструкцию «это не функция». Это функция. Предположим, вы хотите сгруппировать, а не UserId, но по имени, и вы хотите, чтобы группа была нечувствительной к регистру. Тогда вы могли бы использовать:
f=> f.Name.ToUpper()
Так быть функцией не только способ получить сильную типизацию, это также дает более мощные варианты. Вы можете сделать это и в SQL. ]
Конечный бит:
(k, v) => {....}
вы читаться "для каждого USERID & и набор сообщений для этого USERID, сделать ... с ними". Обратите внимание, что имена k & v являются произвольными именами параметров и здесь не так полезны. Я мог бы использовать:
(userid, postsforuserid) => {...}
Собираем все вместе, вы читали
userposts.GroupBy(
userpost => userpost.UserId,
userpost => userpost,
(userid, postsforuserid) => {...})
вслух как:
Группа userposts от UserId; для каждой группы, возьмите все посты для этого id; теперь для каждой группы возьмите userId и все его сообщения и сделайте ... с ними
------------------------- ----------
Итак, вы видите, видя, делегат не очень помогает:
void Main()
{
Del k = delegate (UserPost post) { return post.UserId; };
Del v = delegate (UserPost post) { return post; };
}
class UserId { }
class UserPost { public UserId UserId { get; set; } }
Я соблазн предложить переименовать ваш вопрос, «Как я должен читать лямбда в GroupBy и других методах Linq? " –