You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#在foreach循环中修改List元素的可行解决方案求助

你遇到的是C#中foreach遍历的枚举器限制——枚举器会跟踪集合的版本,遍历过程中修改集合元素(尤其是修改集合长度)会抛出InvalidOperationException,同时你的原有实现还存在性能、安全隐患,下面是直接可用的优化方案:

方案1:使用for循环遍历索引(直接修改原集合,保留原索引)

直接遍历List的索引即可规避foreach的修改限制,同时匹配原有索引位置,不需要额外创建集合:

// 提前开启连接复用,避免重复创建连接
for (int i = 0; i < friendsOnline.Count; i++)
{
    string currentEmail = friendsOnline[i];
    // 使用参数化查询避免SQL注入风险
    string query = "SELECT `username` FROM `accounts` WHERE email = @email";
    using (var cmd = new MySqlCommand(query, conn))
    {
        cmd.Parameters.AddWithValue("@email", currentEmail);
        using (var rdr = cmd.ExecuteReader())
        {
            if (rdr.Read())
            {
                // 直接按索引修改原集合元素,完全匹配原有位置
                friendsOnline[i] = rdr.GetString(0);
            }
        }
    }
}

方案2:使用等长新集合存储结果(避免修改原集合遍历异常,索引完全对齐)

如果你需要保留原始的邮箱列表不被修改,可以初始化一个和原List长度完全相同的新集合,按索引赋值即可保证索引匹配,不会出现索引错位问题:

// 初始化新列表,索引和原列表完全一一对应
List<string> friendsUsername = new List<string>(friendsOnline.Count);
for (int i = 0; i < friendsOnline.Count; i++)
{
    string currentEmail = friendsOnline[i];
    string query = "SELECT `username` FROM `accounts` WHERE email = @email";
    using (var cmd = new MySqlCommand(query, conn))
    {
        cmd.Parameters.AddWithValue("@email", currentEmail);
        using (var rdr = cmd.ExecuteReader())
        {
            // 查询不到用户名时保留原邮箱,避免空值
            friendsUsername.Add(rdr.Read() ? rdr.GetString(0) : currentEmail);
        }
    }
}
// 最终friendsUsername的索引和原friendsOnline完全对应

高阶优化:批量查询降低数据库IO

如果在线好友数量较多,循环单次查询数据库效率很低,可以改用IN条件批量查询所有结果,再映射回原索引:

// 拼接参数化的IN条件,一次性查询所有邮箱对应的用户名
var paramList = new List<MySqlParameter>();
string inClause = string.Join(",", friendsOnline.Select((email, idx) => 
{
    string paramName = $"@email{idx}";
    paramList.Add(new MySqlParameter(paramName, email));
    return paramName;
}));
string query = $"SELECT `email`, `username` FROM `accounts` WHERE email IN ({inClause})";

// 建立邮箱到用户名的映射字典
var emailToUsername = new Dictionary<string, string>();
using (var cmd = new MySqlCommand(query, conn))
{
    cmd.Parameters.AddRange(paramList.ToArray());
    using (var rdr = cmd.ExecuteReader())
    {
        while (rdr.Read())
        {
            emailToUsername[rdr.GetString("email")] = rdr.GetString("username");
        }
    }
}

// 按索引更新原集合,只做一次内存遍历,性能提升明显
for (int i = 0; i < friendsOnline.Count; i++)
{
    if (emailToUsername.TryGetValue(friendsOnline[i], out string username))
    {
        friendsOnline[i] = username;
    }
}

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:54:04