修改IEnumerable foreach与List. foreach中的结构体
本文关键字:foreach 结构体 IEnumerable List 修改 | 更新日期: 2023-09-27 18:05:14
这个问题是关于结构体的。
说我定义:
struct Complex
{
public double real, imaginary;
}
如果我尝试:
var numbers = new[]
{
new Complex() { real = 1, imaginary = 1 },
new Complex() { real = -1, imaginary = -1 }
};
foreach ( var z in numbers )
{
z.real += 1;
}
我得到编译错误:Error: cannot modify members of 'complex' because it is a 'foreach iteration variable'
然而,var numbers = new List<Complex>();
numbers.Add( new Complex() { real = 1, imaginary = 1 } );
numbers.Add( new Complex() { real = -1, imaginary = -1 } );
numbers.ForEach( z => z.real += 1 );
编译时没有错误。记住"foreach"编译错误,这里有没有理由不给出编译时错误?
TL;
- c# 尝试保护你不受自己的伤害
- 如果你足够努力,你将能够做坏事——语言并不能保护你免受你可能做的每一件蠢事
- 可变结构是不好的
是否有任何理由不给出编译时错误呢?
是的。你只是修改了一个参数,这完全没问题。参数不被认为是只读的,而foreach
循环中的迭代变量被认为是只读的。来自c# 5规范第8.8.4节:
在foreach语句执行期间,迭代变量表示当前正在对其执行迭代的集合元素。如果内嵌语句试图修改迭代变量(通过赋值或++和——操作符)或将迭代变量作为ref或out形参传递,则会发生编译时错误。
这些都不意味着使用可变变量是一个好主意-它也不意味着你的ForEach
循环将做你想要的。(毕竟参数是通过值传递给委托的。)
如果您真的想在foreach
版本中做类似的事情(同样无效,但是嘿…),只需在改变字段的结构中编写方法,然后从循环中调用它。这是完全正确的…
// Bad code! Valid, but horrible
foreach (var z in numbers)
{
z.SetReal(z.real + 1);
}
它仍然不会修改列表中的值…但是它不会在编译时失败。