0

オブジェクトが別のオブジェクトよりも古いかどうかを基本的に検出するオブジェクトに IEqualityComparer を実装しようとしています。次のより単純な例は、私が達成しようとしていることを合成します:

class Program
{
    static void Main(string[] args)
    {
        var authorsList = new List<Author>()
        {
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=11 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=20 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=14 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Trevor", Lastname = "Smith", Age=15 },
            new Author{ Firstname = "Brian", Lastname = "Smith", Age=11 },
            new Author{ Firstname = "Billy", Lastname = "Smith", Age=11 },
        };
        var authorsListExcept = new List<Author>()
        {
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
        };
        var authorsList2 = authorsList
            .Except(authorsListExcept, new AuthorUpdatedComparer()).ToList();
    }
}

class Author
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public int Age { get; set; }
}

class AuthorUpdatedComparer : IEqualityComparer<Author>
{
    public bool Equals(Author x, Author y)
    {
        return x.Age >= y.Age;
    }

    public int GetHashCode(Author obj)
    {
        //Check whether the object is null 
        if (Object.ReferenceEquals(obj, null)) return 0;

        int FirstnameHash = (obj.Firstname ?? "").GetHashCode();
        int LastnameHash = (obj.Lastname ?? "").GetHashCode();
        int finalResult = FirstnameHash ^ LastnameHash;

        return finalResult;
    }
}

* Bob Smith の年齢は 20 * Bom Smith の年齢は 14 * Trevor Smith の年齢は 15 * Brian Smith の年齢は 11 * Billy Smith の年齢は 11

しかし、代わりに 14 歳のボブ・スミスは含まれていません。デバッグ中に、20 歳の Bob Smith を含めた後の Comparer には、20 歳未満の Bob をすべて除外した比較演算子があるという結論に達しました。

これは私の見解では奇妙な動作であり、authorsListExcept に含まれているものよりも若い、または同じ年齢のもののみを除外する必要があります。私はmsdnのドキュメントを読み込もうとしましたが、それが起こるはずです:フォント: http://msdn.microsoft.com/en-us/library/bb336390(v=vs.100).aspx

誰でも私を助けることができますか?ありがとう、ヒューゴ・サルガド

4

2 に答える 2

1

次の LINQ クエリは、期待どおりの結果を提供します。

var result = 
    authorsList.GroupBy(x => Tuple.Create(x.Firstname, x.Lastname))
               .SelectMany(g => g.Where(x => authorsListExcept.All(e => e.Firstname != x.Firstname || e.Lastname != x.Lastname || e.Age < x.Age)));

次のクエリでもこの結果が生成されます。パフォーマンスが向上するはずです。

var result = 
    authorsList.GroupBy(x => Tuple.Create(x.Firstname, x.Lastname))
               .GroupJoin(authorsListExcept, x => x.Key,
                          x => Tuple.Create(x.Firstname, x.Lastname),
                          (a, e) => a.Where(x => x.Age > e.Select(z => z.Age)
                                                          .DefaultIfEmpty(0)
                                                          .Max()))
               .SelectMany(x => x)

3 番目のオプション (前と同じですが、クエリ構文):

var result = 
    (from a in authorsList
    group a by Tuple.Create(a.Firstname, a.Lastname) into g
    join e in authorsListExcept on g.Key equals Tuple.Create(e.Firstname, e.Lastname) into er
    from age in er.Select(x => x.Age).DefaultIfEmpty()
    select g.Where(x => x.Age > age)).SelectMany(x => x);

インターフェイスは、等しいIEqualityComparer<T>かどうかをチェックするためにあります。注文とは関係ありません。そのため、思い通りに使用することはできません。

一般に、このインターフェイスの実装では、GetHashCode実装とEqualsメソッドの両方で常にまったく同じプロパティ セットを使用する必要があります。

于 2013-09-19T15:01:43.997 に答える
0

あなたが何を望んでいるのか理解できたら、これを試してください。

class Program
{
    static void Main(string[] args)
    {
        var authorsList = new List<Author>()
        {
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=11 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=20 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=14 },
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Trevor", Lastname = "Smith", Age=15 },
            new Author{ Firstname = "Brian", Lastname = "Smith", Age=11 },
            new Author{ Firstname = "Billy", Lastname = "Smith", Age=11 },
        };
        var authorsListExcept = new List<Author>()
        {
            new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
            new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
        };

        var authorsList2 = authorsList.Where(x => !authorsListExcept.Any(y => y.Firstname == x.Firstname && y.Lastname == x.Lastname && x.Age <= y.Age));
    }
}

public class Author
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public int Age { get; set; }
}
于 2013-09-19T15:36:23.043 に答える