18

明示的なキータイプを使用して、一部のオブジェクトでLinqGroupByを実行しようとしています。私はIEqualityComparerGroupByにを渡していないので、ドキュメントによると:

デフォルトの等式比較器Defaultは、キーを比較するために使用されます。

EqualityComparer<T>.Defaultそれはこのようにプロパティを説明します:

プロパティは、 typeがジェネリックインターフェイスを 実装している Defaultかどうかをチェックし、実装している場合は、その実装を使用するを返します。TSystem.IEquatable<T>EqualityComparer<T>

以下のコードでは、Fredオブジェクトの配列をグループ化しています。FredKeyそれらには、を実装する、と呼ばれるキータイプがありますIEquatable<FredKey>

グループ化を機能させるにはこれで十分ですが、グループ化は機能していません。以下の最後の行では、2つのグループが必要ですが、そうではありません。3つの入力項目を含む3つのグループがあります。

グループ化が機能しないのはなぜですか?

class Fred
{
    public string A;
    public string B;
    public FredKey Key
    {
        get { return new FredKey() { A = this.A }; }
    }
}

class FredKey : IEquatable<FredKey>
{
    public string A;
    public bool Equals(FredKey other)
    {
        return A == other.A;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var f = new Fred[]
        {
            new Fred {A = "hello", B = "frog"},
            new Fred {A = "jim", B = "jog"},
            new Fred {A = "hello", B = "bog"},
        };

        var groups = f.GroupBy(x => x.Key);
        Debug.Assert(groups.Count() == 2);  // <--- fails
    }
}
4

2 に答える 2

19

From MSDN

If you implement IEquatable, you should also override the base class implementations of Object::Equals(Object) and GetHashCode() so that their behavior is consistent with that of the IEquatable::Equals method. If you do override Object::Equals(Object), your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class. This ensures that all invocations of the Equals() method return consistent results.

add this to FredKey and it should work

public override int GetHashCode()
    {
        return A.GetHashCode();
    }
于 2009-11-06T11:58:24.523 に答える
6

これは、フィドルを使用した完全な例です。注:この例は、質問の例とは少し異なります。

次のの実装は、のとしてIEquatable機能できます。との両方が含まれていることに注意してください。TKeyGroupByGetHashCodeEquals

public class CustomKey : IEquatable<CustomKey>
{
    public string A { get; set; }
    public string B { get; set; }

    public bool Equals(CustomKey other)
    {
        return other.A == A && other.B == B;
    }

    public override int GetHashCode()
    {
        return string.Format("{0}{1}", A, B).GetHashCode();
    }
}

public class Custom
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}

public static void Main()
{
    var c = new Custom[]
       {
           new Custom {A = "hello", B = "frog" },
           new Custom {A = "jim", B = "jog" },
           new Custom {A = "hello", B = "frog" },
       };

    var groups = c.GroupBy(x => new CustomKey { A = x.A, B = x.B } );
       Console.WriteLine(groups.Count() == 2);  
}
于 2015-11-20T18:25:22.200 に答える