カスタム オブジェクトの LINQ Distinct() メソッドの異常な動作
LINQ to Objects を使用する場合、カスタム オブジェクトを操作するときに Distinct()
メソッドが常に期待どおりの結果を生成するとは限りません。既定では、LINQ は一意性の比較で参照のみを考慮します。
提供されたコード例には、Book
オブジェクトのリストがあり、各オブジェクトには Author
オブジェクトのリストが含まれています。 SelectMany()
を使用して Authors
コレクションを単一のリストにフラット化し、 Distinct()
を呼び出すと、一意の作成者のみが返されることが期待されます。ただし、同じ著者 (Jon Skeet) が 2 回登場していることがわかります。
問題は、LINQ の Distinct()
メソッドがデフォルトでオブジェクト参照を操作することです。リスト内には 2 つの別々の Author
オブジェクトがあるため、LINQ はそれらが同じ値であっても異なるものとみなされます。この問題を解決するには、オブジェクトの一意性を比較する方法を明確に定義するカスタムの等価性実装を提供する必要があります。
Equals メソッドをオーバーライドします
質問で示唆されているように、Author
クラスの Equals()
メソッドをオーバーライドして等価条件を指定できます。ただし、現在の実装では常に true
が返されるため、すべての作成者が同等であるように見えます。
IEquatable インターフェイスを実装する
より適切なアプローチは、クラスに IEquatable<Author>
インターフェースを実装することです。このインターフェイスを使用すると、カスタム等価コンパレータを定義できます。あなたの場合、著者名に基づいて比較できます:
<code class="language-csharp">public class Author : IEquatable<Author> { public bool Equals(Author other) { return FirstName == other.FirstName && LastName == other.LastName; } }</code>
LINQ クエリで作成者を再利用する
IEquatable<Author>
を実装した後、それを使用して Distinct()
メソッドの動作を改善できます。 LINQ クエリを次のように変更します:
<code class="language-csharp">var temp = books.SelectMany(book => book.Authors).DistinctBy(a => new { a.FirstName, a.LastName });</code>
DistinctBy()
とカスタム ラムダ式を使用して FirstName
と LastName
のタプルを定義することで、作成者の一意性を比較する方法を明示的に指定できます。
これらの手順に従うことで、Distinct()
メソッドが重複する作成者を正確に識別し、その値を保持しながら削除することができます。
以上がLINQ Distinct() がカスタム オブジェクトで期待どおりに動作しないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。