我需要在一个列表中对项目进行分组,然后将每组传递给一个函数进行进一步的细化.

var list = new List<MyObj>(); // list is created ad populated elsewhere in code...

var query = list.AsEnumerable();

query = query.Where(x => x.MyProp == true).Select(x => x); // query definition is way more complicated

var grp = query.GroupBy(x => new { x.Name, x.Surname }).ToList();

此处grpList<IGrouping<'a, MyObj>>型.

我可以使用以下工具轻松地遍历我的项目:

foreach (var g in grp)
{
    foreach (var o in g)
    {
        // here "o" is of type MyObj
    }
}

但我不知道如何创建一个函数来接收组并遍历其项:

foreach (var g in grp)
{
    DoSomethingWithGroup(g);
}

这是因为我在grp定义中有一个匿名类型(键).

我试图用自定义类型替换密钥匿名类型:

private class GrpKey
{
    public string Name { get; set; }
    public string Surname { get; set; }
}

/* ... */

var grp = query.GroupBy(x => new GrpKey { Name = x.Name, Surname = x.Surname }).ToList();

这样,grp的类型为List<IGrouping<MyGrpKey, MyObj>>,而不是List<IGrouping<'a, MyObj>>.

然后我可以创建一个函数:

private void DoSomethingWithGroup(IGrouping<MyGrpKey, MyObj>) { /* ... */ }

不幸的是,这种分组方式不再有效:grp现在包含的组与源列表中的项一样多,每个组都有一个项.

推荐答案

而不是像您那样指定方法:

private void DoSomethingWithGroup(IGrouping<MyGrpKey, MyObj>) 

将键和元素分离到其on参数中

private void DoSomethingWithGroup<T>(T groupKey, IEnumerable<MyObj> entities)

通过此更改,您可以执行以下操作:

//Populate list with some dummy data
var list = new List<MyObj>()
{
    new MyObj { Id = 1, MyProp = true, Name = "A", Surname = "B"},
    new MyObj { Id = 2, MyProp = false, Name = "A", Surname = "B"},
    new MyObj { Id = 3, MyProp = true, Name = "B", Surname = "B"},
    new MyObj { Id = 4, MyProp = true, Name = "B", Surname = "B"},
    new MyObj { Id = 5, MyProp = true, Name = "C", Surname = "B"},
}; 

//Perform the grouping
var groups = list
   .Where(x => x.MyProp)
   .GroupBy(x => new { x.Name, x.Surname })
   .ToList();

//Perform some arbitrary action on the group basis
foreach (var group in groups)
{
    DoSomethingWithGroup(group.Key, group);
}

如果DoSomethignWithGroup的实现如下所示:

void DoSomethingWithGroup<T>(T groupKey, IEnumerable<MyObj> entities)
{
    Console.WriteLine(groupKey);
    foreach (var entity in entities)
    {
        Console.WriteLine($"- {entity.Id}");
    }
}

然后输出如下:

{ Name = A, Surname = B }
- 1
{ Name = B, Surname = B }
- 3
- 4
{ Name = C, Surname = B }
- 5

DotnetFiddle link

Csharp相关问答推荐

`Task`只有在C#中等待时才会运行吗?

具有单一导航属性的EF核心一对多关系

在C#中,有没有一种方法可以集中定义跨多个方法使用的XML参数描述符?

方法从数据表中只 Select 一个条件?

每个http请求需要60秒,为什么?

将字节转换为 struct 并返回

如何在C#中创建VS代码中的控制台应用程序时自动生成Main方法

依赖项注入、工厂方法和处置困境

对于PowerShell中的ConvertTo-SecureString方法,Microsoft如何将初始化向量添加到AES加密中的安全字符串?

在扩展方法中,IEnumerable<;T>;不会转换为IEumerable<;T&>

使DefaultIfEmpty返回空

在使用xUnit和Mock执行单元测试时,控制器ViewResult返回空的Model集合

C#AWS S3上载损坏的文件

如何为C#DLL创建补丁程序

仅在ListView的选定项上显示按钮

序列化和反序列化ASP.NETCore.NET 6 C#App中的泛型对象

C#.NET中的Parall.ForAsync?

从C#程序可靠地运行Mercurial&S和HG状态

在Visual Studio中检测源代码文件中的特定单词或模式?

当异步函数被挂起时,所有的值类型都会受到GC的约束吗?