Использование Linq, кроме как не работает, как я думал
List1 содержит элементы { A, B } и List2 содержит элементы { A, B, C }.
Мне нужно вернуть { C } , Когда я использую, кроме расширения Linq. Вместо этого я получаю { A, B}, и если я переверну списки в своем выражении, результат будет { A, B, C }.
Я неправильно понимаю смысл Except? Есть ли еще одно расширение, которое я не вижу, чтобы использовать?
Я просмотрел и попробовал несколько разных сообщений по этому вопросу без успеха до сих пор.
var except = List1.Except(List2); //This is the line I have thus far
EDIT: Да, я сравнивал простые объекты. Я никогда не использовал IEqualityComparer, было интересно узнать об этом.
спасибо всем за помощь. Проблема заключается не в применении компаратора. Связанное сообщение в блоге и пример ниже, где полезно.
4 ответов
Если вы храните ссылочные типы в вашем списке, вы должны убедиться, что есть способ сравнения объектов на равенство. В противном случае они будут проверены путем сравнения, если они ссылаются на один и тот же адрес.
можно реализовать IEqualityComparer<T>
и отправить его в качестве параметра кроме()
вы просто перепутали порядок аргументов. Я вижу, где возникла эта путаница, потому что официальная документация не так полезно, как могло бы быть:
создает разность двух последовательностей с помощью компаратора равенства по умолчанию для сравнения значений.
Если вы не разбираетесь в теории множеств, может быть неясно, что установить разницу на самом деле-это не просто то, что отличается между множествами. В реальность, Except
возвращает список элементов в первом наборе, которых нет во втором наборе.
попробуйте это:
var except = List2.Except(List1); // { C }
Так Просто для полноты...
// 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;
}
}
}
как раз для Ref: Я хотел сравнить USB-накопители, подключенные и доступные для системы.
Итак, это класс, который реализует интерфейс IEqualityComparer
public class DriveInfoEqualityComparer : IEqualityComparer<DriveInfo>
{
public bool Equals(DriveInfo x, DriveInfo y)
{
if (object.ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
// compare with Drive Level
return x.VolumeLabel.Equals(y.VolumeLabel);
}
public int GetHashCode(DriveInfo obj)
{
return obj.VolumeLabel.GetHashCode();
}
}
и вы можете использовать его в таком виде
var newDeviceLst = DriveInfo.GetDrives()
.ToList()
.Except(inMemoryDrives, new DriveInfoEqualityComparer())
.ToList();