Код становится немного проще, если мы реализуем IEqualityComparer<Customer>
. Это означает, что мы создаем класс, который использует собственную логику, чтобы определить, равны ли два клиента.
public class CustomerNameEqualityComparer : IEqualityComparer<Customer>
{
public bool Equals(Customer x, Customer y)
{
return string.Equals(x?.Name, y?.Name, StringComparison.CurrentCultureIgnoreCase);
}
public int GetHashCode(Customer obj)
{
return obj.Name?.GetHashCode() ?? 0;
}
}
Согласно этому классу, два клиента равны, если у них одинаковое имя. Удобство состоит в том, что мы можем использовать это сравнение без фактического изменения класса Customer
, поскольку это не может всегда быть способом, которым мы хотим сравнивать клиентов.
Мы можем сделать это без этого, но это приводит к множеству сложных Where
функций, которые сравнивают имена. Если вы собираетесь сравнивать элементы, используя особую логику сравнения, то проще создать сравнение один раз и использовать его повторно.
Если мы сделали это (учитывая, что firstList
и secondList
оба List):
var customersFromFirstListNotInSecondList = firstList.Except(secondList);
Это не сработало бы, потому что для сравнения двух списков использовалось бы равенство ссылок вместо поиска совпадающих имен. Но если мы сделаем это:
var customersFromFirstListNotInSecondList =
firstList.Except(secondList, new CustomerNameEqualityComparer());
Он будет сравнивать клиентов в двух списках, просто сопоставляя их имена.
Этот класс сравнения также облегчает реализацию второго шага:
var matchingButNotMigrated =
firstList.Intersect(secondList, new CustomerNameEqualityComparer())
.Where(customer => customer.Source != "migrated");
Возвращает элементы из обоих списков (пересечение), снова сравнивая их по именам. Если у него есть элементы в обоих списках, он исключает те, которые были перенесены.