Использование Linq, кроме того, что я не работаю, как я думал

List1 содержит элементы {A, B} и List2 содержит элементы {A, B, C}.

Мне нужно вернуть {C}, когда я использую Extension Linq extension. Вместо этого я возвращаюсь {A, B}, и если я переворачиваю списки в моем выражении, результат получается {A, B, C}.

Неужели я не понимаю смысл Исключения? Есть ли другое расширение, которое я не вижу?

Я просмотрел и пробовал несколько разных сообщений по этому вопросу без успеха до сих пор.

var except = List1.Except(List2); //This is the line I have thus far

EDIT: Да, я сравнивал простые объекты. Я никогда не использовал IEqualityComparer, было интересно узнать об этом.

Спасибо всем за помощь. Проблема заключалась не в применении компаратора. Связанное сообщение в блоге и пример ниже, где полезно.

Ответ 1

Если вы сохраняете ссылочные типы в своем списке, вы должны убедиться, что есть способ сравнить объекты для равенства. В противном случае они будут проверяться путем сравнения, если они ссылаются на один и тот же адрес.

Вы можете реализовать IEqualityComparer<T> и отправить его в качестве параметра в Except(). Здесь вы можете найти сообщение в блоге.

Ответ 2

Вы просто путаете порядок аргументов. Я вижу, где эта путаница возникла, потому что официальная документация не так полезна, как может быть:

Производит заданное различие двух последовательностей с помощью сравнения по умолчанию для сравнения значений.

Если вы не разбираетесь в теории множеств, может быть неясно, что именно установить разницу на самом деле - это не просто то, что отличается между наборами. В действительности Except возвращает список элементов в первом наборе, которые не находятся во втором наборе.

Попробуйте следующее:

var except = List2.Except(List1); // { C }

Ответ 3

Итак, просто для полноты...

// Except gives you the items in the first set but not the second
    var InList1ButNotList2 = List1.Except(List2);
    var InList2ButNotList1 = List2.Except(List1);
// Intersect gives you the items that are common to both lists    
    var InBothLists = List1.Intersect(List2);

Изменить: поскольку в ваших списках содержатся объекты, которые необходимо передать в IEqualityComparer для вашего класса... Вот что вы, кроме как будет выглядеть с образцом IEqualityComparer на основе созданных объектов...:)

// Except gives you the items in the first set but not the second
        var equalityComparer = new MyClassEqualityComparer();
        var InList1ButNotList2 = List1.Except(List2, equalityComparer);
        var InList2ButNotList1 = List2.Except(List1, equalityComparer);
// Intersect gives you the items that are common to both lists    
        var InBothLists = List1.Intersect(List2);

public class MyClass
{
    public int i;
    public int j;
}

class MyClassEqualityComparer : IEqualityComparer<MyClass>
{
    public bool Equals(MyClass x, MyClass y)
    {
        return x.i == y.i &&
               x.j == y.j;
    }

    public int GetHashCode(MyClass obj)
    {
        unchecked
        {
            if (obj == null)
                return 0;
            int hashCode = obj.i.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.i.GetHashCode();
            return hashCode;
        }
    }
}