2016-09-26 231 views
1

我有一个FilterItems(称为filter)的列表。每个FilterItem由一个字符串&组成一个布尔值。例如“0”和假。List.Contains在通过foreach循环进行交互时不起作用

我已经宣布了名单,像这样:

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

我然后通过数据表列迭代,其目的是从列添加每一个数值为过滤器 - 如果出现两次的值 - 不要将重复条目添加到过滤器列表中。这是我在做什么:

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循环 - 但是我不明白为什么,因为过滤器List是在该循环之外声明的。我试过在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 
    } 
} 

的第2次。载有被称为(foreach循环的同一迭代内)它正确变为真,只是没有当foreach循环围绕再次迭代。

+1

显示'FilterItem'的代码。我的猜测是它不会覆盖'Equals'和'GetHashCode',这意味着'Contains'将做引用相等而不是值相等。 – juharr

回答

2

'问题是,即使当myItem与列表中已有的项目相同时,Contained的结果始终为假' 事实上,它不是 - 您始终在实例化新对象,而.Contains方法只会比较引用。 在这里做的最好的方法是检查是否已经存在具有相同的属性列表上的项目:

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

应该做的伎俩,因为你是在比较不引用,但实际性能一个物品。

+0

这很好,谢谢! –

0

this线程。载有()使用默认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方法时将触发相应的方法。