【C#】ForEach vs foreach

这两种写法表面上类似 ,但实际上在某些情况下行为差异很大,尤其是多线程场景。我们来逐条对比讲明白👇


✅ 简单说,区别在于:

特性 EntityList.ToList().ForEach(...) foreach (var item in EntityList)
是否复制集合 ✅ 先复制一份快照 ❌ 原地遍历原始集合
是否线程安全 ✅ 更安全(如果其他线程可能修改原集合) ⚠️ 有并发修改风险
是否可以修改原集合 不会影响循环 修改时可能抛异常
性能 ❌ 多了一次 ToList() 复制,略慢 ✅ 更快,少一次复制
语义直观性 ✅ 有点"防御性编程"的感觉 ✅ 更自然、常用

👀 举个例子说明:

csharp 复制代码
foreach (var item in multiCamEntityList)
{
    // 如果此时另一个线程修改了 multiCamEntityList,就可能抛出异常!
}

但下面这样:

csharp 复制代码
multiCamEntityList.ToList().ForEach(item =>
{
    // 遍历的是复制后的 List,不怕原始集合被改!
});

所以:

你在并发环境下(如摄像头采集线程),推荐 ToList().ForEach(),能避免"集合修改时遍历"的异常。


💡 ForEach vs foreach 的语法风格区别

这个只是风格上的:

csharp 复制代码
// 更函数式写法(链式操作场景多):
list.ToList().ForEach(item => Console.WriteLine(item));

// 更经典 C# 写法:
foreach (var item in list)
    Console.WriteLine(item);

✅ 实战建议

如果你代码在 多线程环境下(比如采集线程)

csharp 复制代码
multiCamEntityList.ToList().ForEach(item =>
{
    // ✅ 安全地遍历副本
});

如果你明确知道这个集合 不会被其他线程修改,追求性能:

csharp 复制代码
foreach (var item in multiCamEntityList)
{
    // ✅ 省一次复制,快一点
}

List<T>.ForEach 的一个"经典坑":


ForEach 不能用 breakcontinuereturn 来控制循环!

比如这个写法是错误的期望

csharp 复制代码
multiCamEntityList.ToList().ForEach(item =>
{
    if (item.Name == "Camera2")
        break;  // ❌ 语法错误:break 不能用于 lambda 表达式
});

编译器会直接报错:

❌ "Control cannot leave the body of an anonymous method, lambda expression or local function"


✅ 原因解释

  • ForEach(...) 接收的是一个 Action<T>,也就是一个委托
  • break / continue / return 是控制循环结构本身的,不能跨越 lambda 的边界。

✅ 正确做法:用传统 foreach

csharp 复制代码
foreach (var item in multiCamEntityList)
{
    if (item.Name == "Camera2")
        break; // ✅ OK,能跳出
}

🔁 总结

操作 foreach ToList().ForEach()
break ✅ 支持 ❌ 不支持
continue ✅ 支持 ❌ 不支持
return ✅ 支持 ❌ 不支持
性能 ✅ 更好 ❌ 有额外复制(调用 ToList()
可读性 ✅ 更清晰 ⚠️ 略偏函数式、调试不方便

相关推荐
做一位快乐的码农12 分钟前
基于Spring Boot的旅行足迹分享社区的设计与实现/基于java的在线论坛系统
java·开发语言·spring boot
爱编程的鱼2 小时前
C# 数组&C# 多维数组
数据结构·算法·c#
techdashen2 小时前
性能比拼: .NET (C#) vs. Fiber (Go)
golang·c#·.net
code bean4 小时前
【C#】获取不重复的编码(递增,非GUID)
开发语言·c#
阿里嘎多哈基米5 小时前
二、JVM 入门——(三)栈
java·开发语言·jvm·线程·
雷达学弱狗5 小时前
anaconda本身有一个python环境(base),想用别的环境就是用anaconda命令行往anaconda里创建虚拟环境
开发语言·python
燃尽余火5 小时前
Knife4j 文档展示异常的小坑
java·开发语言·spring
爬虫程序猿6 小时前
利用 Java 爬虫按关键字搜索 1688 商品详情 API 返回值说明实战指南
java·开发语言·爬虫
Bling_Bling_16 小时前
ES6新语法特性(第二篇)
开发语言·前端·es6
乘风归趣6 小时前
spire.doc在word中生成公式
java·开发语言·word