Отличный не работа с LINQ к Объектам

Выберите Ubuntu, Одна панель управления-> Добавляет папку от этого компьютера и щелчка правой кнопкой по окну файлового браузера и выбирает Выставочные Скрытые файлы. enter image description here

112
задан Joe 20 December 2016 в 14:58
поделиться

4 ответа

LINQ Distinct не так умен, когда дело доходит до настраиваемых объектов.

Все, что он делает, это просматривает ваш список и видит, что в нем есть два разных объекта (его не волнует, что они имеют те же значения для полей-членов).

Одним из способов решения проблемы является реализация интерфейса IEquatable, как показано здесь .

Если вы измените свой класс Author таким образом, он должен работать.

public class Author : IEquatable<Author>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public bool Equals(Author other)
    {
        if (FirstName == other.FirstName && LastName == other.LastName)
            return true;

        return false;
    }

    public override int GetHashCode()
    {
        int hashFirstName = FirstName == null ? 0 : FirstName.GetHashCode();
        int hashLastName = LastName == null ? 0 : LastName.GetHashCode();

        return hashFirstName ^ hashLastName;
    }
}

Попробуйте это как DotNetFiddle

148
ответ дан 24 November 2019 в 02:46
поделиться

Метод Distinct () проверяет ссылочное равенство для ссылочных типов. Это означает, что он ищет буквально один и тот же дублированный объект, а не разные объекты, содержащие одинаковые значения.

Существует перегрузка , которая принимает IEqualityComparer , поэтому вы можете указать разные логика для определения того, равен ли данный объект другому.

Если вы хотите, чтобы автор обычно вел себя как нормальный объект (т. е. только ссылочное равенство), но для целей Distinct проверять равенство по значениям имен, используйте IEqualityComparer . Если вы всегда хотите, чтобы объекты Author сравнивались на основе значений имени, тогда переопределяет GetHashCode и Equals , или реализовать IEquatable .

Двумя элементами интерфейса IEqualityComparer являются Equals и GetHashCode . Ваша логика определения равенства двух объектов Author выглядит так, если строки имени и фамилии совпадают.

public class AuthorEquals : IEqualityComparer<Author>
{
    public bool Equals(Author left, Author right)
    {
        if((object)left == null && (object)right == null)
        {
            return true;
        }
        if((object)left == null || (object)right == null)
        {
            return false;
        }
        return left.FirstName == right.FirstName && left.LastName == right.LastName;
    }

    public int GetHashCode(Author author)
    {
        return (author.FirstName + author.LastName).GetHashCode();
    }
}
65
ответ дан 24 November 2019 в 02:46
поделиться

Distinct () выполняет сравнение на равенство по умолчанию для объектов в перечисляемом списке. Если вы не переопределили Equals () и GetHashCode () , тогда он использует реализацию по умолчанию для объекта , который сравнивает ссылки.

Простое решение состоит в том, чтобы добавить правильную реализацию Equals () и GetHashCode () ко всем классам, которые участвуют в графе объектов, который вы сравниваете (например, Книга и Автор) .

Интерфейс IEqualityComparer - это удобство, которое позволяет реализовать Equals () и GetHashCode () в отдельном классе, когда у вас нет доступа к внутренним компонентам классов, которые необходимо сравнить, или если вы используете другой метод сравнения.

20
ответ дан 24 November 2019 в 02:46
поделиться

Вы переопределили Equals (), но убедитесь, что вы также переопределили GetHashCode ()

10
ответ дан 24 November 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: