![](/img/trans.png)
[英]How can I filter a list using generics and Linq extension methods?
[英]How can I rewrite Linq Extension Methods as delegates?
我问了这个问题, 如何使用Dapper和多重映射按特定顺序返回一对多记录?
答案是肯定的,但我不明白为什么会起作用。 我不懂,因为我不知道该怎么读。
如何将其重写为代表? 我只想查看函数而不是lambda,这样我就可以看到它。
var groupedPosts = userposts.GroupBy(f => f.UserId, posts => posts, (k, v) =>
new User()
{
UserId = k,
Name = v.FirstOrDefault().Name,
Posts = v.Select(f => new Post() { Id = f.Id,
Title= f.Title,
Content = f.Content})
}).ToList();
我对这部分最感兴趣:
f => f.UserId, posts => posts,
及其与
(k, v)
在那之后,我相信了。
您的意思是您想看到以下内容:
public static int fId(Foo f)
{
return f.Id;
}
public static Foo fPosts(Foo f)
{
return f;
}
public static User fSelect(int k, IEnumerable<Foo> v )
{
return new User()
{
UserId = k,
Name = v.FirstOrDefault().Name,
Posts = v.Select(f => new Post()
{
Id = f.Id,
Title = f.Title,
Content = f.Content
})
};
}
var groupedPosts = userposts.GroupBy(fId, fPosts, fSelect);
重要的是:fId返回int
。 fPosts返回Foo
。 因此,fSelect的参数为int
和IEnumerable<Foo>
。
GroupBy是一种扩展方法, 这里有一些重载。 您的示例使用的重载具有以下内容。
第一个参数( f => f.UserId
)是所谓的键选择器-这将确定每个组的键。
第二个参数( posts => posts
)是值选择器-这将确定组中将包含哪种类型的值
第三个参数( (k, v)
)称为结果选择器,使您在实现该组之前可以再执行一步。 这样,您可以访问键 ( UserId
)作为第一个参数和一个集合值 (该值将包含在组中UserId
所有Posts
),这使您能够随意更改/过滤/投影结果。
因此,例如,如果省略了第三个参数,那么结果将是group,其中键是UserId
,而Groups中的值是Posts
,但是有了第三个参数,我们现在可以访问UserId(键)和Posts(值)并将其投影到新的类型User
。
阅读答案为:
按UserId分组用户帖子; 对于每个群组,请获取该ID的所有帖子; 现在,对于每个组,获取userId及其所有帖子,并对其进行处理。
说明
表达式f => f.UserId
, posts => posts
看起来像是函数。 但事实并非如此。 好吧,它们是,但是有点……不好,这令人困惑。 他们正在做的事情是填写C#语言中不存在的某些语法。
关键是,如何与GroupBy()
方法进行通信:
如果C#支持以下语法可能会很好:
var groupedPosts = userposts.GroupBy( UserId, this, (k, v) => {...});
但是您可以立即看到它永远无法编译。 你必须向他解释说,编译器UserId
是指财产UserPost
那个名字,并且this
范围限定为依次在每个userpost。 在泛型和lambdas之前,.net通常通过使用字符串作为字段名来解决此类问题:
var groupedPosts = userposts.GroupBy( "UserId", "", (k, v) => {...});
然后必须进行一些运行时反射,才能将该字符串转换为属性名称,然后获取一个值,并意识到“”表示整个UserPost
但是在C#中,我们喜欢强类型。 而且,lambda提供了一种可爱但并非立即显而易见的方式来以强类型方式“命名”属性:
f=> f.UserId
你看? 阅读此书不只是作为一个函数,而是为该属性命名:“我想要每个userpost的UserId”
同样,您可以“命名”整个实体:
f => f // means exactly the same as posts=>posts
(函数x=>x
在计算机科学中称为身份函数)。 这就是为什么很难“可视化”代表的原因。 lambda被用作标识字段或属性的简洁, 强类型的方式。
[如果很清楚,让我现在撤消“这不是函数”的声明。 它是一个功能。 假设您要按名称而不是UserId分组,而要按名称分组, 并且希望分组不区分大小写。 然后,您可以使用:
f=> f.Name.ToUpper()
因此,成为一个函数不仅是获得强类型的方法,它还提供了更强大的选择。 您也可以在SQL中执行此操作。 ]
最后一点:
(k, v) => {....}
然后,您将其读为“对于每个userId&,以及该userId的帖子集,请对它们进行...”。 请注意,名称k和v是任意参数名称,在这里并不是很有用。 我可能用过:
(userid, postsforuserid) => {...}
汇集全部,您阅读
userposts.GroupBy(
userpost => userpost.UserId,
userpost => userpost,
(userid, postsforuserid) => {...})
大声说:
按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; } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.