【问题标题】:Remove Single Element From Collection in Foreach从 Foreach 中的集合中删除单个元素
【发布时间】:2018-09-10 18:31:35
【问题描述】:

只是想知道在 foreach 循环中从集合中删除单个元素而不保存它以在循环外执行是否不安全/错误形式/只是看起来很脏。我知道如果你必须继续迭代,它可能会打破循环(在某些情况下,只是抛出一个错误),但在这种情况下你不需要再次迭代,因为当你找到你是什么时你正在使用一个 break 语句寻找。

例子:

List<string> strings = new List<string>() { "A", "B", "C" };
foreach(string s in strings)
{
    if (s == "B")
    {
        strings.Remove("B");
        break;
    }
}

这很糟糕吗?我通常会将其编写为向后循环或将 stringToRemove 缓存在一个变量中(显然名称为 stringToRemove),但我只是想知道其他人对此有何感受。

【问题讨论】:

  • 虽然这不会出错,但它仍然是代码异味

标签: c# collections syntax


【解决方案1】:

而不是使用foreach 循环并且有一些混乱/hacky 的代码。只需使用RemoveAll() 方法即可:

strings.RemoveAll(x => x == "B");

小提琴here

【讨论】:

    【解决方案2】:

    你不能用 foreach 删除,因为 foreach 使用 yield 关键字,它不允许修改 Why?

    maccettura 的回答还可以,但如果您关心性能,请不要在此使用 LINQ 因为 LINQ 基本上 无论如何都会迭代整个列表,所以您只想删除第一个值,所以只需使用旧样式 - for 或 while。您的代码不好,因为您使用“==”来比较字符串。

    您的代码可能如下所示:

    解决方案一: for 循环比 foreach 慢,这种做法是为了简单。

    List<string> strings = new List<string>() { "A", "B", "C" };
    for(int i=0;i<=strings.Count;i++)
    {
        if (strings[i].Equals("B")) //don't use == to compare string in C#
        {
            strings.RemoveAt(i);
            break;
        }
    }
    

    解决方案 2: 更好的性能,可能会很复杂

    List<string> strings = new List<string>() { "A", "B", "C" };
    int deletePosition=0; 
    bool isFound=false;
    foreach(string s in strings)
    {
        deletePosition++;
        if (s.Equals("B")) //don't use "==" to compare string
        {
            isFound=true;
            break;
        }
    }
    
    if(deletePosition<strings.Count-- && isFound)
    {
        strings.RemoveAt(deletePosition);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-02-06
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 2012-05-13
      相关资源
      最近更新 更多