C#Group由几个嵌套属性和列表值组成

我有这个对象结构:

public class Root { public int Value1; public int Value2; public List NestedAList; } public class NestedA { public List NestedBList; public List NestedCList; } public class NestedB{ public int ValueB; public int ValueB2; } public class NestedC{ public int ValueC; public int ValueC2; } 

我需要使用Root类中的所有值和它的嵌套列表对根对象进行分组。 我已经玩了一段时间,无法弄清楚如何/或者我是否可以在一个单独的组声明中做到这一点,或者最好的方法来实现这一点。

编辑:我需要按根属性,嵌套A属性,嵌套B属性和嵌套C属性分组的项目。 所以它是有道理的:我的真实对象有更多的属性,只显示我需要分组的属性,并可以用作起点。

提前致谢。

如果我们有这个元素

 Root Value1 = 1 Value2 = 2 NestedAList = [ {NestedBList = [ {ValueB=2, ValueB2=3} ] NestedCList = [ {ValueC=5, ValueC2=11} ]} ] 

它应与这一组合在一起:

 Root Value1 = 1 Value2 = 2 NestedAList = [ {NestedBList = [ {ValueB=2, ValueB2=3} ] NestedCList = [ {ValueC=5, ValueC2=11} ]} ] 

但不是这个:

 Root Value1 = 1 Value2 = 2 NestedAList = [ {NestedBList = [ {ValueB=2, ValueB2=3}, { ValueB= 1, ValueB2=4} ] NestedCList = [ {ValueC=5, ValueC2=11} ]} ] 

要完成此任务,您可以为层次结构中的每个类重写Equals()GetHashCode()方法。 这可能有点棘手,例如,像这样:

 public class Root { public int Value1; public int Value2; public List NestedAList; public override bool Equals(object obj) { Root other = obj as Root; if (other == null) return false; return this.Value1 == other.Value1 && this.Value2 == other.Value2 && this.NestedAList.SequenceEqual(other.NestedAList); } public override int GetHashCode() { unchecked { int hasha = 19; foreach (NestedA na in NestedAList) { hasha = hasha * 31 + na.GetHashCode(); } return (Value1 ^ Value1 ^ hasha).GetHashCode(); } } } public class NestedA { public List NestedBList; public List NestedCList; public override bool Equals(object obj) { NestedA other = obj as NestedA; if (other == null) return false; return NestedBList.SequenceEqual(other.NestedBList) && NestedCList.SequenceEqual(other.NestedCList); } public override int GetHashCode() { unchecked { int hashb = 19; foreach (NestedB nb in NestedBList) { hashb = hashb * 31 + nb.GetHashCode(); } int hashc = 19; foreach (NestedC nc in NestedCList) { hashc = hashc * 31 + nc.GetHashCode(); } return (hashb ^ hashc).GetHashCode(); } } } public class NestedB{ public int ValueB; public int ValueB2; public override bool Equals(object obj) { NestedB other = obj as NestedB; if (other == null) return false; return this.ValueB == other.ValueB && this.ValueB2 == other.ValueB2; } public override int GetHashCode() { return (ValueB ^ ValueB2).GetHashCode(); } } public class NestedC{ public int ValueC; public int ValueC2; public override bool Equals(object obj) { NestedC other = obj as NestedC; if (other == null) return false; return this.ValueC == other.ValueC && this.ValueC2 == other.ValueC2; } public override int GetHashCode() { return (ValueC ^ ValueC2).GetHashCode(); } } 

之后,您可以轻松选择唯一的根(每个唯一的根代表一个组):

 roots.Distinct().ToList() 

使用GoupBy()结果相同:

 roots.GroupBy(r => r).Select(g => g.First()).ToList() 

计算每组中的元素:

 roots.GroupBy(r => r).Select(g => g.Count()) 

枚举第一组中的元素:

 roots.GroupBy(r => r).First().Select(g => g) 

如果您不关心列表中的元素顺序,请使用Enumerable.All而不是SequenceEqual

编辑:此外,在这种情况下,您必须更改哈希码生成alghoritm。 例如,像这样: hashb = hashb + nb.GetHashCode() * 31; (有关可能的算法的其他信息)