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>、列挙子は をスローします。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

コレクションの反復処理中にコレクションから要素を削除する場合は、次のように逆方向に反復処理します。

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 に答える
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 に答える
1

反復しているシーケンスから何かを削除しないでください!

したがって、代わりに次のようにします。

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