C中的foreach struct怪异编译错误#
namespace MyNamespace
{
public struct MyStruct
{
public string MyString;
public int MyInt;
public bool MyBool;
}
public class MyClass
{
private List<MyStruct> MyPrivateVariable;
public List<MyStruct> MyVariable
{
get
{
if (MyPrivateVariable == null)
{
MyPrivateVariable = new List<MyStruct>();
MyPrivateVariable.Add(new MyStruct());
MyPrivateVariable.Add(new MyStruct());
}
return MyPrivateVariable;
}
}
public void MyLoop()
{
foreach (MyStruct ms in MyVariable)
{
// Doesn't compile, but it works if you execute it through the Immediate window, or in Quickwatch
ms.MyBool = false;
// Compiles, works
MyFunction(ms);
}
}
public void MyFunction(MyStruct ms)
{
ms.MyBool = false;
}
}
}
对此有何合理的解释?C中的foreach struct怪异编译错误#
编译器回报:
Error: Cannot modify members of 'ms' because it is 'foreach iteration variable'
编辑:
额外的问题:
我只是想从MyFunction
改变一个字符串,它实际上并没有更新ms
。但是:如果我去quickwatch并在那里分配相同的值,它会更新ms
。为什么会发生这种情况,如果它不应该编译在第一位,不应该quickwatch抛出异常?
EDIT2:
好,见效快的手表也适用于的ms
副本,所以这就是为什么我可以修改它的价值,它实际上并没有改变的MyPrivateVariable
内容。
结构有值类型的语义。因此,对结构实例所做的任何修改都不会影响原始实例。 C#编译器试图警告你这一点。
C#不会在“foreach(MyStruct ms ...)”中通过引用来迭代结构,因此该上下文中的ms是不可变的。
用类代替MyStruct。
QuickWatch可以操纵堆栈上的值类型。
有时候在一个简单的暴露字段'Holder
您无法更改迭代变量引用的内容:也就是说,您无法将该变量指向其他实例(要找出原因,请参阅Why is The Iteration Variable in a C# foreach statement read-only?)。
'修改'结构(值类型)创建该类型的新实例,因此语句ms.MyBool = false
没有意义。
至MyFunction(ms)
调用编译,因为它副本ms
操作(虽然它仍然不会做你所期望的)。
那么为什么我可以在Quick Watch中修改它们?没关系,那也适用于结构的副本,呃为什么结构还存在? – bevacqua 2010-09-24 19:28:07
@Nico:结构有一个目的,但*可变*结构几乎从来没有做过。 – 2010-09-24 19:30:08
@Nico:你正在做的是修改一个副本,然后扔掉。它本质上是一个没有操作。 – 2010-09-24 20:40:41
什么是编译器错误? – 2010-09-24 19:18:51
编译器消息说什么? – CodingGorilla 2010-09-24 19:19:01
什么是编译器错误信息? – EJC 2010-09-24 19:19:02