LINQ Group通过多个ref-type字段; 自定义EqualityComparer

Pet*_*ter 2 c# linq group-by iequalitycomparer

因此,我已经在SO和其他地方查看了大约20个例子,但是没有找到一个涵盖我正在尝试做的事情.这个 - 我可以指定我的显式类型比较器内联吗? - 看起来像我需要的,但不够远(或者我不明白如何进一步采取它).

  • 我有一个LoadData列表,LoadData对象包含引用和值类型的字段
  • 需要对ref和value字段的混合进行分组,将输出投影为匿名类型
  • 需要(我认为)提供自定义IEqualityComparer来指定如何比较GroupBy字段,但它们是匿名类型

    private class LoadData
    {
        public PeriodEndDto PeriodEnd { get; set; }
        public ComponentDto Component { get; set; }
        public string GroupCode { get; set; }
        public string PortfolioCode { get; set; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

我到目前为止最好的GroupBy查询:

var distinctLoads = list.GroupBy(
    dl => new { PeriodEnd = dl.PeriodEnd, 
                Component = dl.Component, 
                GroupCode = dl.GroupCode },
    (key, data) => new {PeriodEnd = key.PeriodEnd, 
                Component = key.Component, 
                GroupCode = key.GroupCode, 
                PortfolioList = data.Select(d=>d.PortfolioCode)
                                    .Aggregate((g1, g2) => g1 + "," + g2)},
    null);
Run Code Online (Sandbox Code Playgroud)

这组,但仍有重复.

  1. 如何指定自定义代码来比较GroupBy字段?例如,可以通过Component.Code比较组件.

Jon*_*eet 8

这里的问题是你的密钥类型是匿名的,这意味着你不能声明一个IEqualityComparer<T>为该密钥类型实现的类.虽然可以编写一个比较器,以自定义方式比较匿名类型的相等性(通过泛型方法,委托和类型推断),但它不会非常令人愉快.

两个最简单的选择可能是:

  • 使匿名类型"只是工作"被忽略equals/GetHashCode的中PeriodEndDtoComponentDto.如果你想在任何地方使用自然平等,这可能是最安全的选择.我建议实施IEquatable<T>,以及
  • 不要使用匿名类型分组-使用名为类型,然后你可以重写GetHashCodeEquals上,或者你可以写在正常的方式自定义相等比较.

编辑:ProjectionEqualityComparer不会真的有效.写一些类似的东西是可行的 - 有一种CompositeEqualityComparer允许你从几个"投影+比较器"对创建一个相等比较器.然而,与匿名类型相比,它会非常难看.