2016-06-17 9 views
1

Linqでリストを照会したいが、私の例では2つの要素(Name、Status)を含む他のリストでフィルタしたい。 これは私の問題に適応した古い質問に触発されています。 LINQ: "contains" and a Lambda query リストを含むcontainsを含むLinqクエリフィルタ<T>複数の要素

"contains"メソッドを使用しようとしましたが、私のリストをフィルタリングできませんでした。

私は2つの建物(2つ、5つ)で結果を得る必要があります 誰かが私が停止しているアイデアはありますか?

おかげ

BLOCKQUOTE

public class Building 
    { 
     public enum StatusType 
     { 
      open, 
      closed, 
      weird, 
     }; 

     public string Name { get; set; } 
     public StatusType Status { get; set; } 
    } 

    private static readonly List<Building> BuildingList = new List<Building>() 
    { 
     new Building() {Name = "one", Status = Building.StatusType.open}, 
     new Building() {Name = "two", Status = Building.StatusType.closed}, 
     new Building() {Name = "three", Status = Building.StatusType.weird}, 
     new Building() {Name = "four", Status = Building.StatusType.open}, 
     new Building() {Name = "five", Status = Building.StatusType.closed}, 
     new Building() {Name = "six", Status = Building.StatusType.weird}, 
    }; 

    private void GetResult() 
    { 
     var buildingSelect = new List<Building> 
     { 
      new Building() {Name = "two", Status = Building.StatusType.closed}, 
      new Building() {Name = "five", Status = Building.StatusType.closed} 
     }; 

     var q = (from building in BuildingList 
      where buildingSelect.Contains(building.Name, building.Status) 
      select building).ToList(); 

     dataGridView1.DataSource = q; 
    } 

答えて

1

あなたのLINQの主な問題は、あなたがBuildingを実装していないため、LINQは、唯一の彼らの参照で比較することができます2 Building秒、の平等を比較しようとしているということですIEquatable<Building>object.Equalsを上書きしないでください。

これを解決する1つの方法は、@ Wayneの答えに一致するかどうかを比較するプロパティを手動で指定することです。

他の方法は、あるBuildingインスタンスは、その参照によりそれらの値によって同一視されることを意図していない場合は、IEquatable<Building>を実装し、object.Equalsを上書き:

public class Building : IEquatable<Building> 
{ 
    public Building(string name, StatusType status) 
    { 
     Name = name; 
     Status = status; 
    } 

    public enum StatusType 
    { 
     open, 
     closed, 
     weird, 
    }; 

    public string Name { get; } 

    public StatusType Status { get; } 

    public static bool operator ==(Building left, Building right) 
     => Equals(left, right); 

    public static bool operator !=(Building left, Building right) 
     => !Equals(left, right); 

    public override bool Equals(object obj) => Equals(obj as Building); 

    public bool Equals(Building other) 
    { 
     if (ReferenceEquals(this, other)) 
     { 
      return true; 
     } 

     if (ReferenceEquals(other, null) || GetType() != other.GetType()) 
     { 
      return false; 
     } 

     return Name == other.Name && Status == other.Status; 
    } 

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

そうすれば、あなたの元のコードは動作しますList.Containsなるため今度は、IEquatable<Building>の実装を使用して、同等かどうかを確認してください。

+0

ありがとうrexcfnghk、これを私は学び、IEquatableの実装を実験しました。 Containsは現在、元のコードで若干の更新を行っています。> 'buildingSelect.Contains(new Building(building.Name、building.Status))'のどこにありますか?リストの削除も機能しています。すばらしいです。どうもありがとう。 – GYCO50

+0

私の答えがあなたを助けたら、それを答えとして受け入れることを検討してください – rexcfnghk

0

あなたはこのような何かを意味ですか?

var q = from b in BuildingList 
     from bs in buildingSelect 
     where b.Name == bs.Name && b.Status == bs.Status 
     select b; 

または多分:

var q = from b in BuildingList 
     join bs in buildingSelect 
     on new { b.Name, b.Status } equals new { bs.Name, bs.Status } 
     select b; 
+0

感謝。どちらの提案もうまくいきます。 – GYCO50

+0

私はこのようないくつかの行を削除することによってbuildingSelectリストを変更する必要があるとして、私は問題が残されてきた:「コードbuildingSelect.Remove(新しいビルを(){ 名= 『2』、ステータス= Building.StatusType.closed}) ; 'これはうまくいかない。これを修正するためのアイデア。よろしく。 – GYCO50

+0

rexcfnghkの答えを参照してください。 'List.Remove'は、' Building'オブジェクトが 'GetHashCode'と' Equals'を実装していない場合、 'new Building'が' buildingSelect'コレクションに存在することは決してなく、定義ではできません除去された。 – lesscode

0

これは意味がある場合は、クラス自体の等価を上書きすることができます。

それとも、このように、Any()で通常のチェックを行います。このため

var q = (from building in BuildingList 
     where buildingSelect.Any(b => b.Name == building.Name 
             && b.Status == building.Status) 
     select building).ToList(); 
関連する問題