Distinct не работает с LINQ to Objects



class Program
{
static void Main(string[] args)
{
List<Book> books = new List<Book>
{
new Book
{
Name="C# in Depth",
Authors = new List<Author>
{
new Author
{
FirstName = "Jon", LastName="Skeet"
},
new Author
{
FirstName = "Jon", LastName="Skeet"
},
}
},
new Book
{
Name="LINQ in Action",
Authors = new List<Author>
{
new Author
{
FirstName = "Fabrice", LastName="Marguerie"
},
new Author
{
FirstName = "Steve", LastName="Eichert"
},
new Author
{
FirstName = "Jim", LastName="Wooley"
},
}
},
};


var temp = books.SelectMany(book => book.Authors).Distinct();
foreach (var author in temp)
{
Console.WriteLine(author.FirstName + " " + author.LastName);
}

Console.Read();
}

}
public class Book
{
public string Name { get; set; }
public List<Author> Authors { get; set; }
}
public class Author
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override bool Equals(object obj)
{
return true;
//if (obj.GetType() != typeof(Author)) return false;
//else return ((Author)obj).FirstName == this.FirstName && ((Author)obj).FirstName == this.LastName;
}

}


это основано на примере в "LINQ in Action". Листинг 4.16.



это печатает Джон Скит дважды. Зачем? Я даже попытался переопределить метод Equals в классе Author. Все еще отчетливо не работает. Чего мне не хватает?



изменить:
Я добавил == А != перегрузка оператора тоже. По-прежнему никакой помощи.



 public static bool operator ==(Author a, Author b)
{
return true;
}
public static bool operator !=(Author a, Author b)
{
return false;
}
542   1  

1 ответ:

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

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

один обходной путь заключается в реализации IEquatable интерфейс, как показано здесь.

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

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

Comments

    Ничего не найдено.