简体   繁体   English

在 foreach 循环中修改列表

[英]Modifying list inside foreach loop

I have a construction similar to this (but a lot more complicated):我有一个与此类似的结构(但复杂得多):

var list = new List<string>();

// .. populate list ..

foreach(var item in list)
{
    DoFunction(list);
}

public void DoFunction(List<string> list)
{
    if(someCondition == true)
    {
        // .. modify list in here ..
    }
}

Now, I understand that its not possible to edit the collection you're foreaching through, but how do you jump out of the loop gracefully if you do have to edit the list (without a try catch statement)?现在,我知道不可能编辑您正在遍历的集合,但是如果您必须编辑列表(没有try catch语句),您如何优雅地跳出循环? Is there some way to tell if the list has been edited?有什么方法可以判断列表是否已被编辑? Can you edit the list and quickly break;你能编辑列表并快速break; before it notices?在它注意到之前?

Yes, you could break, if that's what you really want.是的,你可以打破,如果那是你真正想要的。 An exception won't be thrown until the for loop tries to grab the next item from the list.for循环尝试从列表中获取下一项之前,不会引发异常。

But I've found it's easiest just to create and iterate across a copy of the list so you don't have to worry about it.但我发现创建和迭代列表的副本是最简单的,因此您不必担心它。

foreach(var item in list.ToList())

The added performance overhead of an extra, untouched list is generally negligible compared to the maintainability costs of more complex code.与更复杂代码的可维护性成本相比,额外的未触及列表所增加的性能开销通常可以忽略不计。

Rather than use a foreach construct, a for loop would allow you to alter the list.与其使用foreach结构,不如使用for循环来更改列表。

for (var x = 0; x < list.Count; x++) {

}

It's hard to offer useful advice without knowing what kinds of edits are being made.如果不知道正在进行何种编辑,就很难提供有用的建议。 The pattern that I've found is has the most general-purpose value, though, to just construct a new list.不过,我发现的模式具有最通用的价值,仅用于构建一个新列表。

For example, if you need to look at each item and decide between removing it, leaving it as-is, or inserting items after it, you could use a pattern like this:例如,如果您需要查看每个项目并决定是删除它、保持原样还是在其后插入项目,您可以使用如下模式:

IEnumerable<string> butcherTheList(IEnumerable<string> input)
{
    foreach (string current in input)
    {
        if(case1(current))  
        {
            yield return current;
        }
        else if(case2(current))
        {
            yield return current;
            yield return someFunc(current);
        }
        // default behavior is to yield nothing, effectively removing the item
    }
}

List<string> newList = butcherTheList(input).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM