需要帮助理解一些代码示例?

Need help understanding some code sample?

最近在浏览本论坛的最新 c# question/answers 时,我偶然发现了一段 linq-to-xml 代码,我无法完全理解,但作为一个喜欢使用 linq-to 的人-xml 这让我很烦恼,因为我无法一步一步地弄清楚这个过程到底在做什么。

这是代码片段

var cons = xdoc.Descendants("xref")
.Where(x=>x.Attribute("rid").Value.Contains("ref"))
.GroupBy(x=>x.Parent)
.Select(grp=> new
        {
            Parent = grp.Key,
            ConsecutiveNodes = grp.Select((n, i)=> new
                                          {
                                            Index = i+1,
                                            Node = n
                                          }),
            Count = grp.Count()
        })
.ToList();

谁能给我详细解释一下

.Select(grp=> new
        {
            Parent = grp.Key,
            ConsecutiveNodes = grp.Select((n, i)=> new
                                          {
                                            Index = i+1,
                                            Node = n
                                          }),
            Count = grp.Count()
        })

正在干什么?我从来没有在另一个匿名类型中使用过匿名类型,我也没有得到多参数 lambda 表达式 (n,i)=>new...(除了一个参数是字符而另一个是索引这一简单的事情)?它在这段代码中到底做了什么?

这是文件(由代码的 OP 发布)xml file

Select 方法有一个允许您使用索引的重载

you can see the documentation here

让我们通过将您的查询分成两部分来了解 Linq

第一部分

        var cons = xdoc.Descendants("xref")
                     .Where(x => x.Attribute("rid").Value.Contains("ref"))
                     .GroupBy(x => x.Parent);

第二部分

        var consSelect = cons.Select(grp => new
                     {
                         Parent = grp.Key,
                         ConsecutiveNodes = grp.Select((n, i) => new
                         {
                             Index = i + 1,
                             Node = n
                         }),
                         Count = grp.Count()
                     })
                     .ToList();

在第一部分中,您将获取所有外部参照并按其父级对 XML 进行分组。 每当您对元素进行分组时,分组的元素将被视为键。

因此在第二部分中,grp.key 为您提供父元素,count 为您提供每个组中的外部参照数,连续节点再次是 {index, Node } 对象的集合,其中包含每个外部参照作为节点和 'i' 作为索引(i 只是一个迭代器)