Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何作为委托重写Linq扩展方法?_C#_.net_Linq_Lambda_Delegates - Fatal编程技术网

C# 如何作为委托重写Linq扩展方法?

C# 如何作为委托重写Linq扩展方法?,c#,.net,linq,lambda,delegates,C#,.net,Linq,Lambda,Delegates,我问这个问题, 答案很好,但我不明白它为什么有效。我不明白,因为我不知道怎么读 作为代表,我如何重写?我想看函数,而不是lambda,这样我才能可视化它 var groupedPosts = userposts.GroupBy(f => f.UserId, posts => posts, (k, v) => new User() { UserId = k, Name = v.FirstOrDefault().Name,

我问这个问题,

答案很好,但我不明白它为什么有效。我不明白,因为我不知道怎么读

作为代表,我如何重写?我想看函数,而不是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);
publicstaticintfid(foof)
{
返回f.Id;
}
公共静态Foo fPosts(Foo f)
{
返回f;
}
公共静态用户fSelect(int k,IEnumerable v)
{
返回新用户()
{
UserId=k,
Name=v.FirstOrDefault().Name,
Posts=v.Select(f=>newpost()
{
Id=f.Id,
Title=f.Title,
内容=f.内容
})
};
}
var groupedPosts=userposts.GroupBy(fId、fPosts、fSelect);

重要提示:fId返回
int
。和fPosts返回
Foo
。因此,fSelect的参数是
int
IEnumerable

GroupBy是一种扩展方法,其中包含多个重载。 示例中使用的重载具有以下读数

第一个参数(
f=>f.UserId
是一个所谓的键选择器-这将确定每个组的键

第二个参数(
posts=>posts
)是值选择器-这将确定组中包含的值类型

第三个参数(
(k,v)
被称为结果选择器,它在实现组之前为您提供了一个额外的步骤。这可以访问键(
UserId
)作为第一个参数和集合值(
UserId
)这使您能够随意更改/过滤/投影结果

例如,如果省略了第三个参数,那么结果将是组,其中键是
用户ID
,组中的值是
Posts
,但是使用第三个参数,我们现在可以访问用户ID(键)和Posts(值)并将它们投射到一个新类型中-
用户

将您的答案读为:

按用户ID对用户帖子进行分组;对于每个组,获取该id的所有帖子;现在,对于每个组,获取用户ID及其所有帖子并执行。。。和他们在一起

解释

表达式
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) => {...});
然后必须进行一些运行时反射,才能将该字符串转换为propertyname,然后获取一个值,从而认识到“”表示整个
UserPost

但在C#中,我们喜欢强打字。lambda提供了一种可爱但不明显的方式,可以用强类型的方式“命名”属性:

f=> f.UserId
看到了吗?与其说是函数,不如说是命名属性:“我想要每个userpost的UserId”

同样,您可以“命名”整个实体:

f => f // means exactly the same as posts=>posts
(函数
x=>x
在计算机科学中称为身份函数)。这就是为什么很难“形象化”代表的原因。lambda被用作一种简洁、强类型的方法来标识字段或属性

[如果这是非常清楚的,现在让我收回'it's not a function'语句。它是一个函数。假设您希望按名称分组,而不是按用户名分组,并且希望分组不区分大小写。然后您可以使用:

f=> f.Name.ToUpper()
因此,作为一个函数不仅仅是获得强类型的一种方式,它还提供了更强大的选项。您也可以在SQL中这样做。 ]

最后一点:

(k, v) => {....}
然后读作“对于每个userId&以及该userId的一组帖子,用它们做”。请注意,名称k&v是任意参数名称,在这里没有多大帮助。我可能会使用:

(userid, postsforuserid) => {...}
把这一切放在一起,你会读到

    userposts.GroupBy(
       userpost  =>  userpost.UserId, 
       userpost  =>  userpost,
       (userid, postsforuserid) => {...})
大声说:

按用户ID对用户帖子进行分组;对于每个组,获取该id的所有帖子;现在,对于每个组,获取用户ID及其所有帖子并执行。。。和他们在一起

-----------------------------------

因此,你看,看到代理没有多大帮助:

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

谢谢请问它是哪一种?我说不出来。这是Foo userposts?是的,userposts是Foo的集合。我建议将您的问题重命名为“我应该如何阅读GroupBy和其他Linq方法中的lambdas?”