質問

だから私はこれについての約20の例をとてもそして他の場所で見ていましたが、私がやろうとしていることをカバーするものを見つけていません。これは - インラインで指定できますか? - 私が必要なもののように見えますが、それほど遠くない(または私はそれをさらにそれを取る方法を理解していません)。

  • 私はloadDataのリストを持っています、loadDataオブジェクトには、参照タイプと値の型の両方のフィールドがあります
  • REFフィールドと値のフィールドの混在をグループ化する必要がある場合は、出力を匿名型
  • に投影する必要があります。
  • groupbyフィールドの比較方法を指定するためのカスタムIEQUALITEComparerを提供する必要がありますが、それらは匿名型

    です。
    private class LoadData
    {
        public PeriodEndDto PeriodEnd { get; set; }
        public ComponentDto Component { get; set; }
        public string GroupCode { get; set; }
        public string PortfolioCode { get; set; }
    }
    

最高のグループビークエリこれまでに進んでいます:

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);
.

このグループですが、まだ重複しています。

  1. GroupByフィールドを比較するためのカスタムコードを指定する方法たとえば、コンポーネントはComponent.Codeによって比較できます。
役に立ちましたか?

解決

問題はあなたのキーの種類が匿名であることです。つまり、そのキータイプのIEqualityComparer<T>を実装するクラスを宣言することはできません。 になるのは、(一般的な方法、代議員、および型推論を介して)カスタム方法で匿名のタイプを比較する比較器を書くことは、それはひどく心地よいものではないでしょう。

2つの最も簡単なオプションはおそらく:

  • PeriodEndDtoComponentDtoのequals / gethashcodeをオーバーライドすることで、匿名のタイプ「Not Work」を作ります。どこでも使用したいという自然な平等がある場合、これはおそらく最高のオプションです。 IEquatable<T>を実装することをお勧めします
  • グループ化に匿名タイプを使用しない - 名前付きタイプを使用してから、それ以降のGetHashCodeEqualsをオーバーライドすることも、通常の方法でカスタムの平等比較器を書くこともできます。

編集:ProjectionEqualityComparerは実際には機能しません。似たようなものを書くことは可能です - いくつかの「投影+比較器」ペアから平等比較器を作成することを可能にする一種のCompositeEqualityComparerを書くことが可能であろう。それは匿名のタイプと比べてかなり醜いでしょう。

他のヒント

編集:

Jon SKEETが指摘しているように、この解決策はそれほど難しいとは思っていない場合は、GethashCodeを実装するのを忘れていたので、それよりも優れているようです。ジョンコードを実装する必要があるので、Jonは彼の答えで「ひどく快適ではない」と言うように、このアプローチを行います。おそらく、これはフレームワーク内のEqualityComparer<T>.Create()の(いわゆる「不可能な」)存在についても説明である。何がそうでないかの例として、参考のために答えを残します。

オリジナルアンサー:

.NET 4.5で導入されたComparer<T>.Createパターンによって提案されたアプローチを使用することができます(ただし、EqualityComparer<T>には不明なことがありません)。これを行うには、DelegateEqualityComparer<T>クラスを作成します。

class DelegateEqualityComparer<T> : EqualityComparer<T>
{
    private readonly Func<T, T, bool> _equalityComparison;

    private DelegateEqualityComparer(Func<T, T, bool> equalityComparison)
    {
        if (equalityComparison == null)
            throw new ArgumentNullException("equalityComparison");
        _equalityComparison = equalityComparison;
    }

    public override bool Equals(T x, T y)
    {
        return _equalityComparison(x, y);
    }

    public static DelegateEqualityComparer<T> Create(
        Func<T, T, bool> equalityComparison)
    {
        return new DelegateEqualityComparer<T>(equalityComparison);
    }
}
. 次に、GroupByメソッドの周囲にラッパーを書きます。これらのメソッドは、DelegateをFunc<TKey, TKey, bool>インスタンスに囲み、それを対応するGroupByメソッドに渡します。例:

public static class EnumerableExt
{
    public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        Func<TKey, TKey, bool> equalityComparison)
    {
        return source.GroupBy(
            keySelector,
            DelegateEqualityComparer<TKey>.Create(equalityComparison);
    }
}
.

最後に、あなたの通話サイトで、IEqualityComparer<TKey>引数のこの式のようなものを使うでしょう:

(a, b) => a.PeriodEnd.Equals(b.PeriodEnd)
    && a.Component.Code.Equals(b.Component.Code)
    && a.GroupCode.Equals(b.GroupCode)
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top