Foreach 循环访问列表的错误

本文关键字:错误 列表 访问 循环 Foreach | 更新日期: 2023-09-27 18:37:09

我有以下一段代码给我带来了问题,我将不胜感激任何帮助:

private static string CreateOptionString(List<VehicleOption> Options)
{
    StringBuilder returnValue = new StringBuilder();
    foreach (VehicleOption option in Options)
    {
        if (option.OptionStatus == ExtendedResponse.OptionState.Included)
        {
            if (returnValue.Length > 0)
            {
                returnValue.Append(", ");
            }
            returnValue.Append(option.OptionName);
        }
    }
    return returnValue.ToString();
}

最初的问题是我收到一个 System.InvalidOperationException:在我的 foreach 循环上修改了集合错误。

1)我仍然无法弄清楚为什么会出现此错误,因为我在任何地方都看不到它被修改了。

有人建议我将列表复制到新列表并循环浏览新列表。 我这样做了,它摆脱了无效操作异常。 但是,我尝试了 2 种不同的方式处理列表,并且都给了我一个 System.ArgumentException:目标数组不够长。这是我尝试复制列表的两种方法

List<VehicleOption> newOptions = new List<VehicleOption>(Options);

List<VehicleOption> newOptions = new List<VehicleOption>();
newOptions.AddRange(Options);

这两个都给了我一个 System.ArgumentException:目标数组不够长。

2)为什么这两种方法中的任何一种都会给我这个例外?

任何帮助将不胜感激,因为我被难住了。

谢谢!

Foreach 循环访问列表的错误

确保在

迭代集合时没有其他线程更改集合。

此外,另一种方法是:

return string.Join(", ", options.Where(
    op => op.OptionStatus == ExtendedResponse.OptionState.Included));

在这种情况下,这比使用StringBuilder更好,而且(令人惊讶地)更快。

不过,这并不能解决您的问题 - 这可能是由更改集合的不同线程引起的。

我的第一个尝试是:

private static string CreateOptionString(List<VehicleOption> Options)
{
    lock (Options)
    {
        return string.Join(", ", options.Where(
            op => op.OptionStatus == ExtendedResponse.OptionState.Included));
    }
}

但是,当然,如果我们有任何关于其他线程弄乱该集合的信息,那么提供更好的线程安全解决方案会更容易。

听起来Options引用的列表对象正在被另一个线程更改。 这可以解释这两个问题。

  1. 显然,如果另一个线程在您迭代列表时更改列表,您将看到"集合已修改"异常,因为您无法在枚举列表元素时更改列表。
  2. 在后一种情况下,听起来像构造函数和AddRange正在分配数组,然后从提供的枚举中填充它。 如果列表在分配和枚举以填充新阵列之间增长,则突然之间分配的存储将不够大,您将看到此行为。

您需要设计一些锁定机制,以便此代码可以在处理元素或创建副本以供以后处理时阻止可能正在写入列表的任何线程。

好的,我最终解决了这个问题。 我在对该方法的调用周围放置了一个锁(在选项列表中)。 这解决了我所有的问题。