2017-12-08 4 views
0

の二つのリストをマージします。たとえば : リストA - ジョン、ジョナサン、ジェームズ.... リストB - マーサ、ジェーン、ジョナサン.... Unsubscribers - ジョナサンはC#が、これは私のクライアントクラスで同じ値

public static List<Clients> SameClients(List<Clients> A, List<Clients> B) 
    { 
     List<Clients> Unsubscribers = new List<Clients>(); 
     Unsubscribers = A.Intersect(B).ToList(); 
     return Unsubscribers; 
    } 

は、しかし、いくつかの理由のために私は空のリストを取得し、私は何が間違っているのか分かりません。

+1

あなたはそのクラスのプロパティではなく、クラスを比較しました。 'Client'クラスで' Equal'と 'GetHashCode'をオーバーライドする必要があります。ここに例がありますhttps://stackoverflow.com/a/38434457/2946329 –

+0

両方のリストにある「Jonathan」のインスタンスは同じですか?彼らは同じではないように聞こえるのでもちろんリストは空です。クラスのリストを比較するには、独自のcomparerを実装します。 – Equalsk

答えて

4

問題を比較するときは、オブジェクトを比較するときにEqualsGethashcodeを使用します。これらの2つの方法をオーバーライドして、ニーズに合わせて独自の実装を提供することができます。以下の2つの方法をオーバーライドする方法については、下記の回答があります。

通常、エンティティ/それらを呼びたいと思っています)非常にシンプルで、比較実装の詳細を私のモデルから遠ざけています。その場合、あなたはIEqualityComparer<TSource>を実装し、ここだけNameプロパティに基づいてIEqualityComprarerの実装例だIEqualityComparer

にかかるIntersectsのオーバーロードを使用することができます...基本的に

public class ClientNameEqualityComparer : IEqualityComparer<Clients> 
{ 
    public bool Equals(Clients c1, Clients c2) 
    { 
     if (c2 == null && c1 == null) 
      return true; 
     else if (c1 == null | c2 == null) 
      return false; 
     else if(c1.Name == c2.Name) 
      return true; 
     else 
      return false; 
    } 

    public int GetHashCode(Client c) 
    { 
     return c.Name.GetHashCode(); 
    } 
} 

、実装上記の場合はの2つのインスタンスがNameプロパティの同じ値を持つ場合、それらは等しいとみなされます。あなたがfollowigを行うことができます今すぐ

...

A.Intersect(B, new ClientNameEqualityComparer()).ToList(); 

そして、それはあなたが期待している結果を生成します...

1

IntersectGetHashCodeと、デフォルトでEquals使用しますが、上書きされていませんそのため、ちょうどcompares referencesであるObject.Equalsが使用されます。すべてのクライアントインスタンスはnewで初期化されるため、それらのインスタンスが等しい値であっても別々のインスタンスになります。だから、Intersectは、共通のクライアントがないと「考える」のです。

あなたはいくつかの選択肢があります。

  • IEqualityComparer<Clients>を実装し、Intersect(または他の多くのLINQメソッド)に渡します。これは、さまざまな要件のために別の比較子を実装することができ、あなたが
  • 元のクラスを変更する必要がないという利点がClientsオーバーライドEqualsGetHashCodeおよび/または
  • ClientsがためにIEquatable<Clients>

を実装してみましょう聞かせています例(他の答えはすでにIEqualityComparer<T>示したので、最後の二つを示す):

public class Clients : IEquatable<Clients> 
{ 
    public string Email { get; set; } 
    public string Name { get; set; } 


    public Clients(string e, string n) 
    { 
     Email = e; 
     Name = n; 
    } 

    public override bool Equals(object obj) 
    { 
     return obj is Clients && this.Equals((Clients)obj); 
    } 

    public bool Equals(Clients other) 
    { 
     return Email == other?.Email == true 
      && Name == other?.Name == true; 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      int hash = 17; 
      hash = hash * 23 + (Email?.GetHashCode() ?? 0); 
      hash = hash * 23 + (Name?.GetHashCode() ?? 0); 
      return hash; 
     } 
    } 
} 

読んワース:

Differences between IEquatable<T>, IEqualityComparer<T>, and overriding .Equals() when using LINQ on a custom object collection?

+0

大変ありがとうございます。現在、サブスクライバーリストは名前を返します。変更する必要があるため、サブスクライバーリストはメールの値を返しますか? – Andrius

+0

@Andrius: 'Unsubscribers'は' Name'を返します。それは名前を返さないリストです。このリストには、他の両方のリストに共通する 'Clients'インスタンスが含まれています。すべての 'Clients'インスタンスには' Name'と 'Email'プロパティがあります。ごめんなさい –

+0

は、私はこの方法を意味します。public static一覧 SameClients(一覧 A、リスト B) { 一覧 Unsubscribersは=新しいリストを(); サブスクライバ= A.Intersect(B).ToList(); 返品不可 } Unsubscribersを返すと、名前のみが取得されますが、メールを受け取る場合はどうなりますか? – Andrius

関連する問題