0

我有一个对象列表,我想删除所有满足条件的对象。这是我的代码:

var listCurrentBuzzCompaigns = _buzzService.GetAllActiveCompaigns().ToList();

listCurrentBuzzCompaigns.ForEach(x => {
    if (x.MayaMembership.MayaProfile.MayaProfileId == profile_id)
        listCurrentBuzzCompaigns.Remove(x);
});

但是一个活动被删除了,下一个没有,下一个是,下一个不是。代码有什么问题?

4

4 回答 4

9

您在迭代列表时正在修改列表,这不好。请改用以下List<T>.RemoveAll方法:

listCurrentBuzzCompaigns.RemoveAll(x => x.MayaMembership.MayaProfile.MayaProfileId == profile_id);

通常,当您使用foreach关键字遍历 a时,如果枚举器检测到列表已被修改,List<T>它将抛出 an 。InvalidOperationException此行为旨在完全防止您遇到的那种错误。不幸的是,该List<T>.ForEach方法在内部不使用枚举器,因此不会抛出异常来警告您可能存在的错误。foreach和之间的这种不一致ForEach对我来说似乎是一个设计缺陷。

更新:正如 AlanT 所指出的,另一种技术是调用ToList. 这是如何做到的:

var listCurrentBuzzCompaigns = _buzzService.GetAllActiveCompaigns()
    .Where(x.MayaMembership.MayaProfile.MayaProfileId != profile_id)
    .ToList();

请注意,我通过更改==为来反转条件!=

于 2012-07-06T14:54:16.200 回答
2

在显示的代码段中,您最好在获取活动时使用 where() 子句来过滤活动,而不是在检索到活动后尝试将其删除。

例如

[TestMethod]
public void TestMethod1() {

   var campaigns = new List<Campaign>(){
       new Campaign {ProfileId = "Jan"},
       new Campaign {ProfileId = "Jan"},
       new Campaign {ProfileId = "Feb"},
       new Campaign {ProfileId = "Mar"},
       new Campaign {ProfileId = "Jan"},
       new Campaign {ProfileId = "Jan"},
   };


   var notJanCampaigns = campaigns.Where(c => c.ProfileId != "Jan");

   Assert.AreEqual(2, notJanCampaigns.Count());

}

class Campaign {
    public string ProfileId { get; set; }
} 

在您的代码中,您将过滤

x.MayaMembership.MayaProfile.MayaProfileId != profile_id
于 2012-07-06T14:59:37.897 回答
2

如果您想在迭代集合时从集合中删除元素,请像这样向后迭代它:

List<Smurf> smurfs = GetSomeSmurfs();
for (in i = smurfs.Count - 1; i >= 0; i--)
{
   Smurf smurfToRemove = smurfs[i];
   if(conditionToRemoveSmurf)
   {
      //Do whatever you need with that smurf before removing it. 
      //(Dispose(), give to azrael, whatever)
      smurfs.Remove(smurfToRemove);
   }
}

实现这一点的相应扩展方法留给读者练习;)

于 2012-07-06T15:00:38.613 回答
1

不要从你正在迭代的序列中删除东西!

所以,改为:

var x = listCurrentBuzzCompaigns.Where(x => x.MayaMemberShip.MayaProfile.PayaProfileId == profile_id).Single();
listCurrentBuzzCompaigns.Remove(x);
于 2012-07-06T14:55:18.810 回答