我不能在foreach循环中删除元素列表

时间:2015-11-22 04:21:14

标签: list

我想通过在方法中传递委托类型并迭代列表来检查人的年龄。 如果我发现那个人还是个孩子......我想把他从名单中删除......因为我已经对他进行了测试,并且不想再次进行测试。 但是我从列表中删除元素后得到例外...例外是我无法在foreach循环中修改集合。我有什么方法可以实现这一点,因为我不想执行操作当人的年龄已经在最后一次手术中决定时再次在同一个人身上。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

命名空间DelegateApp {

/// <summary>
/// A class to define a person
/// </summary>
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    //Our delegate
    public delegate bool FilterDelegate(Person p);

    static void Main(string[] args)
    {

        //Create 4 Person objects
        Person p1 = new Person() { Name = "John", Age = 41 };
        Person p2 = new Person() { Name = "Jane", Age = 69 };
        Person p3 = new Person() { Name = "Jake", Age = 12 };
        Person p4 = new Person() { Name = "Jessie", Age = 25 };

        //Create a list of Person objects and fill it
        List<Person> people = new List<Person>() { p1, p2, p3, p4 };
        DisplayPeople("Children:", people, IsChild);
        DisplayPeople("Adults:", people, IsAdult);
        DisplayPeople("Seniors:", people, IsSenior);

        Console.Read();
    }

    /// <summary>
    /// A method to filter out the people you need
    /// </summary>
    /// <param name="people">A list of people</param>
    /// <param name="filter">A filter</param>
    /// <returns>A filtered list</returns>
    static void DisplayPeople(string title, List<Person> people, FilterDelegate filter)
    {
        Console.WriteLine(title);

        foreach (Person p in people)
        {
            if (filter(p))
            {
                Console.WriteLine("{0}, {1} years old", p.Name, p.Age);
                people.Remove(p);
            }

        }

        Console.Write("\n\n");
    }

    //==========FILTERS===================
    static bool IsChild(Person p)
    {
        return p.Age <= 18;
    }

    static bool IsAdult(Person p)
    {
        return p.Age >= 18;
    }

    static bool IsSenior(Person p)
    {
        return p.Age >= 65;
    }
}

}

1 个答案:

答案 0 :(得分:0)

使用for循环而不是foreach循环。如果您在循环浏览列表时更改列表,则无法使用foreach循环。使用for循环时,您应该在循环中向后计数,以便从末尾删除元素。

for (int i = people.Count - 1; i >= 0; i--)
{
   Person p = people[i];
   if (filter(p))
   {
      Console.WriteLine("{0}, {1} years old", p.Name, p.Age);
      people.RemoveAt(i);
   }
}

倒退的原因是否则你会跳过一些元素。例如,假设您要删除原始列表的元素4和5。如果你向前计数,那么当你的循环计数器为4时,你将删除元素4.因此元素5成为新元素4,元素6成为新元素5.然后在循环的下一次迭代中,你的计数器现在,循环的迭代操作在当前元素5(最初是元素6)上。所以你的原始元素5完全被跳过了。向后计数避免了这种情况。如果您在列表中前进,则每次删除元素时都必须减少循环计数器,这样会更加混乱。