我可以使用匿名类型进行Linq分组吗?

4
我有以下代码,它生成一个包含多个列表的字典;每个列表可以使用数字键检索。
public class myClass
{
    public string Group { get; set; }
    public int GroupIndex { get; set; }
    ...
}

public List<MyClass> myList { get; set; }

private Class IndexedGroup
{
    public int Index { get; set; }
    public IEnumerable<MyClass> Children { get; set; }
}

public Dictionary<int, IEnumerable<MyClass>> GetIndexedGroups(string group)
{
    return myList.Where(a => a.Group == group)
                 .GroupBy(n => n.GroupIndex)
                 .Select(g => new IndexedGroup { Index = g.Key, Children = g })
                 .ToDictionary(key => key.Index, value => value.Children);
}

有没有什么方法可以消除IndexedGroup类?

我尝试在Select方法中使用匿名类型,像这样:

.Select(g => new { Index = g.Key, Children = g })

但是我遇到了类型转换错误。


顺便说一下,如果你发布了确切的错误信息,普通人也可以找出问题所在。 - SLaks
@SLaks。错误信息就像针尖上的圣经,而我正在一台未连接到互联网的计算机上开发。 - Robert Harvey
真的,这将是一条很长的消息。为什么你要在未连接互联网的电脑上进行开发? - SLaks
@SLaks:出于安全考虑。 - Robert Harvey
3个回答

5
IGrouping<T>中的Children转换为IEnumerable<T>,或者显式地向ToDictionary调用传递泛型参数。

参数g是一个实现了IEnumerable<T>IGrouping<T>
隐式泛型调用最终会创建一个Dictionary<int, IGrouping<MyClass>>,而这不能转换为Dictionary<int, IEnumerable<MyClass>>

你的IndexedGroup类避免了此问题,因为它的Children属性明确地声明为IEnumerable<MyClass>

例如:

return myList.Where(a => a.Group == group)
             .GroupBy(n => n.GroupIndex)
             .ToDictionary<int, IEnumerable<MyClass>>(g => g.Key, g => g);

另外,您可能会对ILookup<TKey, TElement> 接口感兴趣。

@Robert:你可以在任何地方进行类型转换。 - SLaks
关于你的例子,ToDictionary<T1, T2> 的参数列表与 ToDictionary() 不同(且不兼容),因此你的示例代码无法工作。 - Robert Harvey
@Robert:你说得对,我忘记了TSource,它太大了,不方便传递。其他两个答案都可以很好地工作,并且更短。 - SLaks

2

你可以完全摒弃Select()并调用.AsEnumerable()

return myList.Where(a => a.Group == group)
             .GroupBy(n => n.GroupIndex)
             .ToDictionary(g => g.Key, g => g.AsEnumerable());

或者您可以将返回类型更改为ILookup,它基本上是您要使用的数据结构:

public ILookup<int, MyClass> GetIndexedGroups(string group)
{
    return myList.Where(a => a.Group == group)
                .ToLookup(n => n.GroupIndex);                    
}

第一种解决方案不会有帮助。 - SLaks
此外,group 是一个上下文关键字。 - SLaks
1
@SLaks:如果没有更多细节,你的评论也不会有任何意义。 - StriplingWarrior
@Stripling:请看我的答案,有详细的解释。你仍然在创建一个Dictionary<int, IGrouping<MyClass>> - SLaks
谢谢。我使用了你的第一个例子。 - Robert Harvey

1

以下方案如何?

return myList.Where(a => a.Group == group)
             .GroupBy(n => n.GroupIndex)
             .ToDictionary(g => g.Key, g => g as IEnumerable<MyClass>);

我更喜欢调用.AsEnumerable()方法,或者像@SLaks那样更改您的ToDictionary签名,因为它可以提供更多的类型安全性。 - StriplingWarrior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接