Edited at

C# LINQ Distinct を自作クラスのコレクションで使う方法

More than 3 years have passed since last update.

自作のクラスを保持するコレクションに対し LINQ の Distinct を使う場合、IEquatableインターフェースを実装する必要があるってことで、いろいろハマったのでメモ。


自作のクラスがこんな感じだったとする


public class MyModel
{
public string ItemID { get; set; }
public string ItemName { get; set; }

public MyModel(string ItemID, string ItemName)
{
this.ItemID = ItemID;
this.ItemName = ItemName;
}
}


List<MyModel> に対し Distinct をしても動かない


List<MyModel> myModels = new List<MyModel>();

//
// もろもろ過程を経て、myModel にデータが格納されていると過程して
//

myModels = myModels.Distinct().ToList(); // 重複削除は行われない

まー、動かないかなーって思ってたけど(例えば何をもって重複と判断するのか的な)、これを思った通りの動きにする場合、MyModelクラスに IEquatable インターフェースを実装する


実装の例

この IEquatable を実装する場合、GetHashCode を override することと、Equals メソッドを実装する必要があるようです(ソースについては後述)


public class MyModel : IEquatable<MyModel>
{
public string ItemID { get; set; }
public string ItemName { get; set; }

public MyModel(string ItemID, string ItemName)
{
this.ItemID = ItemID;
this.ItemName = ItemName;
}

public override int GetHashCode()
{
return this.ItemID.GetHashCode();
}

bool IEquatable<MyModel>.Equals(MyModel myModel)
{
if( myModel == null )
return false;
return (this.ItemID == myModel.ItemID);
}
}

こうすることで、期待通りの動きになった。


ソース

Microsoft Developer Network Enumerable.Distinct メソッド


既定の等値比較子 Default は、IEquatable ジェネリック インターフェイスを実装している型の値を比較するために使用されます。 カスタム データ型を比較するには、このインターフェイスを実装し、その型の GetHashCode メソッドと Equals メソッドを独自に用意する必要があります。