这个问题具体是关于结构.
我说定义:
struct Complex
{
public double real, imaginary;
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试:
var numbers = new[]
{
new Complex() { real = 1, imaginary = 1 },
new Complex() { real = -1, imaginary = -1 }
};
foreach ( var z in numbers )
{
z.real += 1;
}
Run Code Online (Sandbox Code Playgroud)
我收到编译错误: 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 );
Run Code Online (Sandbox Code Playgroud)
编译没有错误.记住'foreach'编译错误,有没有理由不在这里给出编译时错误?
TL; DR:
那么在这里没有给出编译时错误的理由吗?
是.你只是修改一个参数,这绝对没问题.参数不被认为是只读的,而在一个迭代变量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);
}
Run Code Online (Sandbox Code Playgroud)
它仍然不会修改列表中的值...但它不会在编译时失败.