Пересекайтесь с пользовательским IEqualityComparer, используя Linq

Короче говоря: у меня есть 2 коллекции объектов. Один содержит хорошие значения (назовем его «Хорошо»), другие значения по умолчанию (г-н «По умолчанию»). Я хочу, чтобы Пересечение Союза между Хорошим и По умолчанию и По умолчанию. Другими словами: Intersect (Union (Good, Default), Default). Можно подумать, что он разрешен как Default, но здесь он становится сложным: я использую пользовательский IEqualityComparer.

Я получил следующие classы:

class MyClass { public string MyString1; public string MyString2; public string MyString3; } class MyEqualityComparer : IEqualityComparer { public bool Equals(MyClass item1, MyClass item2) { if(item1 == null && item2 == null) return true; else if((item1 != null && item2 == null) || (item1 == null && item2 != null)) return false; return item1.MyString1.Equals(item2.MyString1) && item1.MyString2.Equals(item2.MyString2); } public int GetHashCode(MyClass item) { return new { item.MyString1, item.MyString2 }.GetHashCode(); } } 

Вот характеристика моих коллекций Коллекции Good и Default:

По умолчанию: это большой набор, содержащий все нужные (MyString1, MyString2) пары, но значения MyString3, как вы можете догадаться, значения по умолчанию.

Хорошо: это меньший набор, содержащий в основном элементы, которые находятся в настройке по умолчанию, но с некоторыми хорошими значениями MyString3. Он также имеет некоторые {MyString1, MyString2}, которые находятся за пределами желаемого набора.

Я хочу сделать следующее: Возьмите только элементы из «Хорошего», которые находятся в разделе «По умолчанию», но добавьте в него другие элементы по умолчанию.

Вот, что я думаю, моя лучшая попытка:

 HalfWantedResult = Good.Union(Default, new MyEqualityComparer()); WantedResult= HalfWantedResult.Intersect(Good, new MyEqualityComparer()); 

Я учил, что это должно было сработать, но результат, который я получаю, это, по сути, только хорошие пары {MyString1, MyString2}, но все из набора по умолчанию, так что у меня есть значение по умолчанию. Я также попытался переключить Default и Good последнего Intersect, но получаю тот же результат.

    Прежде всего, это неправильно:

     public bool Equals(MyClass item1, MyClass item2) { return GetHashCode(item1) == GetHashCode(item2); } 

    Если hash-код отличается, разумеется, соответствующие 2 элемента отличаются, но если они равны, не гарантируется, что соответствующие 2 элемента равны.

    Итак, это правильная реализация Equals :

     public bool Equals(MyClass item1, MyClass item2) { if(object.ReferenceEquals(item1, item2)) return true; if(item1 == null || item2 == null) return false; return item1.MyString1.Equals(item2.MyString1) && item1.MyString2.Equals(item2.MyString2); } 

    Как предложил Slacks (ожидая меня), код выглядит следующим образом:

     var Default = new List { new MyClass{MyString1="A",MyString2="A",MyString3="-"}, new MyClass{MyString1="B",MyString2="B",MyString3="-"}, new MyClass{MyString1="X",MyString2="X",MyString3="-"}, new MyClass{MyString1="Y",MyString2="Y",MyString3="-"}, new MyClass{MyString1="Z",MyString2="Z",MyString3="-"}, }; var Good = new List { new MyClass{MyString1="A",MyString2="A",MyString3="+"}, new MyClass{MyString1="B",MyString2="B",MyString3="+"}, new MyClass{MyString1="C",MyString2="C",MyString3="+"}, new MyClass{MyString1="D",MyString2="D",MyString3="+"}, new MyClass{MyString1="E",MyString2="E",MyString3="+"}, }; var wantedResult = Good.Intersect(Default, new MyEqualityComparer()) .Union(Default, new MyEqualityComparer()); // wantedResult: // AA + // BB + // XX - // YY - // ZZ - 

    Вам нужно проверить фактическое равенство, а не только равенство hashcode.

    GetHashCode() не является (и не может быть) без конфликтов, поэтому метод Equals необходим в первую очередь.

    Кроме того, вы можете сделать это гораздо проще, написав

     WantedResult = Good.Concat(Default).Distinct(); 

    Метод Distinct вернет первый элемент каждой пары дубликатов, так что это вернет желаемый результат.

    EDIT : Это должно быть

     WantedResult = Good.Intersect(Default, new MyEqualityComparer()) .Union(Default, new MyEqualityComparer()); 
    Давайте будем гением компьютера.