System.InvalidOperationException: 集合已修改;可能无法执行枚举操作

错误分析报错信息为:System.InvalidOperationException: 集合已修改;可能无法执行枚举操作。
这表明在遍历 m_BIBInfoMap.Values 集合时,集合被修改(例如添加、删除或替换元素),导致枚举器失效。

这是 .NET 中常见的异常,通常发生在使用 foreach 遍历集合时,集合的内容被修改。

具体错误发生在以下代码块中:csharp

foreach (BIB bib in m_BIBInfoMap.Values)
{
    // ...
    m_BIBInfoMap[bib.Id] = CurrentSetBIBBoard; // 修改 m_BIBInfoMap
    // ...
}

在 foreach 遍历 m_BIBInfoMap.Values 时,代码通过 m_BIBInfoMap[bib.Id] = CurrentSetBIBBoard 修改了 m_BIBInfoMap 集合。这会导致正在使用的枚举器失效,抛出 InvalidOperationException。

优化方案为了解决这个问题,我们需要确保在遍历集合时不直接修改它。

以下是几种解决方案,以及优化的代码实现:

方案一:使用 ToList() 创建副本进行遍历通过将 m_BIBInfoMap.Values 转换为一个新的 List,我们可以安全地遍历副本,而不会影响原始集合。

方案二:使用临时集合存储修改内容将需要修改的键值对存储到一个临时集合中,待遍历完成后统一更新 m_BIBInfoMap。

方案三:使用普通 for 循环如果需要直接操作 m_BIBInfoMap,可以通过索引或键值访问,避免使用枚举器。

以下基于 方案一 提供优化后的代码,因为它简单且易于理解,同时保持代码逻辑不变。


优化后的代码csharp

public static void UpdateBIBBoardSectionId(string sectionId, string BIBBoard)
{
    try
    {
        string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings", "BIBBoard.ini");
        StringBuilder sb = new StringBuilder();

        var testSection = GetSection(sectionId);

        // 使用 ToList() 创建副本,避免在遍历时修改集合
        foreach (BIB bib in m_BIBInfoMap.Values.ToList())
        {
            string channelIDbib = bib.ChannelID;
            foreach (TestChannel testChannel1 in testSection.TestChannelMap.Values)
            {
                var channelID = testChannel1.Id;
                if (bib.HardwareStatus == HardwareStatus.Enabled && channelID == channelIDbib)
                {
                    var currentSetBIBBoard = HardwareMgr.CopyBIB(HardwareMgr.BIBMap[BIBBoard]);

                    // 更新 BIB 对象的属性
                    currentSetBIBBoard.Id = bib.Id;
                    currentSetBIBBoard.BIBName = bib.BIBName;
                    currentSetBIBBoard.Life = bib.Life;
                    currentSetBIBBoard.HardwareStatus = bib.HardwareStatus;
                    currentSetBIBBoard.BIBCoords = bib.BIBCoords;
                    currentSetBIBBoard.ChannelID = bib.ChannelID;

                    // 更新 m_BIBInfoMap
                    m_BIBInfoMap[bib.Id] = currentSetBIBBoard;

                    // 更新 TestChannel 的 Bib 属性
                    TestChannel testChannel = GetChannel(channelID);
                    testChannel.Bib = currentSetBIBBoard;
                }
            }
        }

        // 序列化并写入文件
        foreach (string bibID in m_BIBInfoMap.Keys)
        {
            sb.AppendLine(JsonConvert.SerializeObject(m_BIBInfoMap[bibID]));
        }
        File.WriteAllText(filePath, sb.ToString());
    }
    catch (Exception ex)
    {
        // 日志记录,方便调试
        Console.WriteLine($"更新 BIBBoardSectionId 失败: {ex.Message}");
        throw; // 抛出异常以便上层处理
    }
}

优化点详解

  1. 修复集合修改问题:
    • 在 foreach (BIB bib in m_BIBInfoMap.Values) 中添加 .ToList(),将 m_BIBInfoMap.Values 复制到一个新列表中。这样,遍历的是副本,修改原始 m_BIBInfoMap 不会影响遍历过程,解决了 InvalidOperationException。
  2. 改进路径处理:
    • 将文件路径拼接从 AppDomain.CurrentDomain.BaseDirectory + "Settings\\BIBBoard.ini" 改为使用 Path.Combine,提高代码的可读性和跨平台兼容性。
  3. 变量命名优化:
    • 将 fledpath 更名为 filePath,修正拼写错误并提高可读性。
    • 将 sb_1 更名为 sb,简化命名。
    • 将 CurrentSetBIBBoard 更名为 currentSetBIBBoard,遵循 C# 命名规范(变量名首字母小写)。
  4. 异常处理改进:
    • 原代码的 catch 块为空,捕获异常但不做任何处理,这可能导致问题被忽略。优化后添加了日志输出(Console.WriteLine),并重新抛出异常(throw),以便上层代码能够感知并处理异常。
    • 建议在实际生产环境中使用更健壮的日志框架(如 Serilog 或 NLog)代替 Console.WriteLine。
  5. 代码结构优化:
    • 保持逻辑清晰,确保每个步骤(遍历、更新、序列化、写入文件)分块明确。
    • 使用更具描述性的变量名(如 currentSetBIBBoard),提高代码可维护性。

其他建议

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张工在路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值