Использование объединения в двух списках не работает должным образом

1

Я прочитал около тридцати постов на эту тему и подумал, что следую вашим указаниям на письмо.

Вот класс, который я использую:

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}

Что я делаю не так? Я читал кучу разных постов, которые все говорят одно и то же - в основном использование. Я не использую его правильно? Я не получаю никаких ошибок, это просто не дает мне союза, которого я ожидал.

  • 0
    Union добавит 2 списка вместе, не проверяя их значения и не удаляя дубликаты. Вы можете вызвать Distinct () после объединения, и он даст вам уникальные значения без дубликатов
Теги:
linq
c#-4.0

3 ответа

7
Лучший ответ

Проблема заключается в том, что компилятор не знает, как сравнить два UserID objects.It использует по умолчанию компаратора равенства, которое сравнивает ваш объект с помощью references.So, даже если они имеют такое же user_id они рассматриваются как разные, так как ссылки отличаются.

Вы должны сообщить компилятору сравнить ваши объекты на user_id свойства user_id, либо переопределив методы Equals и GetHashCode в вашем классе, либо реализуя [ IEqualityComparer ]. 1

  • 0
    благодарю вас. Это именно то, что мне нужно было сделать!
0

Как предложил 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 содержал только уникальные элементы из обоих списков.

  • 0
    Ваш компаратор не обрабатывает null объекты UserID , и почти наверняка должен.
0

Union удаляет дубликаты (см. Здесь). Это то, что отличает его от Concat.

Однако для этого необходимо обеспечить возможность сравнивать элементы в двух последовательностях так, как вы ожидаете (в двух экземплярах UserId с внутренним значением, равным 10, равны).

Для этого либо предоставите сопоставитель равенства, либо реализуйте IEquatable в классе UserId. В статье MSDN есть пример этого в классе Product.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню