为何Linq ForEach未提供与普通foreach循环相同的编译错误提示?
为什么普通foreach赋值迭代变量报错,List.ForEach却不报错?
先看示例代码:
List<(int integer, string str)> myTupleList; foreach (var tuple in myTupleList) tuple = (tuple.integer, tuple.str); myTupleList.ForEach(tuple => tuple = (tuple.integer, tuple.str));
核心原因是两者的底层机制和编译器校验规则完全不同:
普通foreach的迭代变量是语言层面的只读约束
foreach是C#语法自带的循环结构,编译器会把迭代变量(这里的tuple)标记为只读。因为迭代变量只是当前集合元素的副本,给它赋值不仅不会修改原集合,还属于无意义操作,所以编译器直接触发编译错误,从源头阻止这种无效代码。List.ForEach的参数是委托形参,语法上允许赋值
List的ForEach方法接收的是Action<T>委托,lambda里的tuple是委托方法的局部形参。虽然这个形参也是原元素的副本,赋值同样不会影响原集合,但编译器对普通方法的形参没有只读限制——形参赋值在语法上是合法的(哪怕逻辑上毫无意义),所以不会触发编译错误。
简单说就是:foreach是语言语法,有专属的严格校验;ForEach是普通方法,只遵循普通方法的参数规则。
内容的提问来源于stack exchange,提问作者sandsalamand
相关产品推荐
相关产品推荐

