Я прочитал около тридцати постов на эту тему и подумал, что следую вашим указаниям на письмо.
Вот класс, который я использую:
public class UserID
{
public int user_id { get; set; }
public bool exists { get; set; }
}
Я создал два хороших списка.
List<UserID> List1 = new List<UserID>();
List<UserID> List2 = new List<UserID>();
Я успешно заполнил оба списка.
Я пытаюсь получить список уникальных идентификаторов пользователей. Я нашел метод объединения списков и дал ему шанс.
List<UserID> ResultList = new List<UserID>();
ResultList = List1.Union(List2).ToList();
Вот проблема. После последней строки здесь выполняется ResultList - это всего лишь два списка.
List1 имеет {10, 20, 30, 40} List2 имеет {10, 30, 40, 50, 60}
Я ожидаю, что профсоюз даст мне:
ResultList = {10, 20, 30, 40, 50, 60}
но вместо этого он дает мне:
ResultList = {10, 20, 30, 40, 10, 30, 40, 50, 60}
Что я делаю не так? Я читал кучу разных постов, которые все говорят одно и то же - в основном использование. Я не использую его правильно? Я не получаю никаких ошибок, это просто не дает мне союза, которого я ожидал.
Проблема заключается в том, что компилятор не знает, как сравнить два UserID
objects.It использует по умолчанию компаратора равенства, которое сравнивает ваш объект с помощью references.So, даже если они имеют такое же user_id
они рассматриваются как разные, так как ссылки отличаются.
Вы должны сообщить компилятору сравнить ваши объекты на user_id
свойства user_id
, либо переопределив методы Equals
и GetHashCode
в вашем классе, либо реализуя [ IEqualityComparer
]. 1
Как предложил Selman22, мне нужно было использовать [IEqualityComparer].
Я добавил это в свой код.
public class CompareUserIDs : IEqualityComparer<UserID>
{
public bool Equals(UserID x, UserID y)
{
return x.user_id.Equals(y.user_id);
}
public int GetHashCode(UserID obj)
{
return obj.user_id.GetHashCode();
}
}
Затем я назвал его следующим:
IntermediateResult = List1.Union(List2).ToList();
IEqualityComparer<UserID> customComparer = new CompareResultTables();
IEnumerable<UserID> myresult = IntermediateResult.Distinct(customComparer);
И вуаля! У меня был мой "союз". myresult содержал только уникальные элементы из обоих списков.
null
объекты UserID
, и почти наверняка должен.
Union
удаляет дубликаты (см. Здесь). Это то, что отличает его от Concat
.
Однако для этого необходимо обеспечить возможность сравнивать элементы в двух последовательностях так, как вы ожидаете (в двух экземплярах UserId
с внутренним значением, равным 10, равны).
Для этого либо предоставите сопоставитель равенства, либо реализуйте IEquatable в классе UserId
. В статье MSDN есть пример этого в классе Product
.