2016-09-26 9 views
1

私はFilterItemsのリストを持っています。各FilterItemは、ブール値の文字列&で構成されています。例えば"0"かつfalse。リスト。foreachループを介する際にList.Containsが機能しない

私はそうのようなリスト宣言している:

List<FilterItem> filter = new List<FilterItem>(); 

私は、DataTableの列を反復処理していますが、意図はフィルタにその列からすべての単一の値を追加することです - と値が二回発生した場合 - フィルタリストに繰り返しエントリを追加しないでください。 - 私は、これは、foreachループのbeacuseだと思う - しかし、私

List<FilterItem> filter = new List<FilterItem>(); //initialise new list 
foreach (DataRow row in RawResults.Rows) //For each row in DT 
{ 
    FilterItem myItem = new FilterItem { Name = row.ItemArray[i].ToString(), Checked = CheckState.Checked }; //create item 
    if (!filter.Contains(myItem)) //if item doesn't exist 
    { 
     filter.Add(myItem); //add it 
    } 
} 

を問題が含まれての結果はMYITEMがすでにリスト内の項目と同じであっても、常に偽であるということです。これは私がやっているものですなぜフィルタリストがそのループの外で宣言されているのか理解していない。 foreachループの外側でmyItemを宣言しようとしましたが、それによって差異がゼロになります。

私は次のような場合:

List<FilterItem> filter = new List<FilterItem>(); //initialise new list 
foreach (DataRow row in RawResults.Rows) //For each row in DT 
{ 
    FilterItem myItem = new FilterItem { Name = row.ItemArray[i].ToString(), Checked = CheckState.Checked }; //create item 
    if (!filter.Contains(myItem)) //if item doesn't exist 
    { 
     filter.Add(myItem); //add it 
    } 
    FilterItem myItem = new FilterItem { Name = row.ItemArray[i].ToString(), Checked = CheckState.Checked }; //create item 
    if (!filter.Contains(myItem)) //if item doesn't exist 
    { 
     filter.Add(myItem); //add it 
    } 
} 

.Containsが、それは正しく、trueになります(foreachループの同じ繰り返し内)と呼ばれる2回目は、ちょうどforeachループが再び周りに繰り返されていないとき。

+1

'FilterItem'のコードを表示してください。私の推測は、 'Equals'と' GetHashCode'をオーバーライドしないということです。つまり、 'Contains'は値の平等の代わりに参照の平等を行います。 – juharr

答えて

2

'問題は、myItemが既にリスト内のアイテムと同じ場合でも、Containedの結果が常にfalseであるということです。実際はそうではありません。新しいオブジェクトをインスタンス化しています.Containsメソッドは参照を比較するだけです。

!filter.Any(item => item.Name == myItem.Namae && item.Checked == myItem.Checked); 

はトリックを行う必要がありますあなたがいないの言及はなく、実際の特性を比較している原因、: ここで行うための最善の方法は、すでに同じプロパティのセットで、リスト上の項目があるかどうかを確認することですアイテム。

+0

これはうまく動作します、ありがとう! –

0

thisスレッドによると、.Contains()ほとんどの場合、それは、オブジェクトへの参照を比較し、このように、クラスのデフォルトIEqualityComparerを使用しています。

要素が実際に含まれているかどうかを確認するには、.Any()を使用するか、独自の等価比較器を実装する必要があります。

0

コードnew FilerItemは、新しいフィルタ項目を作成します。その新しい項目は他のオブジェクトとは異なります。たとえプロパティがまったく同じであっても、それは別のインスタンスです。

あなたはそれにあなたの最初のif文を変更した場合:あなたが実際にプロパティを比較します

if(!filter.Any(i => i.Name == myItem.Name && i.Checked == myItem.Checked)) { //... 

。あるいは、FilterItemクラスのEqualsメソッドをオーバーライドしたり、IEquatable<T>を実装したりすることもできます。

0

FilterItemクラス内でEqualsメソッドとGetHashCodeメソッドをオーバーライドすることを検討する必要があります。このように、FilterItemインスタンスを格納するコレクションに応じて、その特定のコレクションのAdd/Containsメソッドを呼び出すと、対応するメソッドがトリガーされます。

関連する問題