2013-05-29 3 views
10

Список1 содержит элементы {A, B} и List2 содержит элементы {A, B, C}.Использование Linq, за исключением того, что я не работаю, как я думал

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

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

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

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

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

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

+1

Что именно в этих списках? –

+0

Каков тип данных ваших товаров. Это класс? Эта ссылка может помочь вам http://stackoverflow.com/questions/1645891/why-isnt-except-linq-comparing-things-properly-using-iequatable – arunlalam

+0

Это простые объекты с несколькими свойствами на данный момент. Я просмотрю вашу ссылку. – Schanckopotamus

ответ

10

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

Вы можете реализовать IEqualityComparer<T> и отправить его как параметр в функцию Except(). Вот blog post, которые могут вам помочь.

+0

Чтобы быть ясным, это решение, которое давно решило мою проблему и является жизнеспособным вариантом, в зависимости от вашего сценария. – Schanckopotamus

6

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

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

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

Попробуйте это:

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

Если изменить порядок списка, я получаю {A, B, C} – Schanckopotamus

4

Так что для полноты ...

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

Edit: Так как ваши списки содержат объекты, которые нужно передать в 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; 
     } 
    } 
} 
+0

InList1ButNotList2 дает {C, B, A}, что и произошло. – Schanckopotamus

+0

@Schanckopotomus Ahh ... ваши списки - объекты, а их свойства равны, но объекты не являются ссылочными равными справа? – Kevin

Смежные вопросы