在C#中Foreach结构奇怪的编译错误

bev*_*qua 3 c# compiler-construction generics 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对此有任何合理的解释吗?

编译器返回:

错误:无法修改'ms'的成员,因为它是'foreach iteration variable'

编辑:

额外的问题:

我只是尝试更改一个字符串MyFunction,它实际上没有更新ms.但是:如果我去快速观察并在那里分配相同的值,它会更新ms.如果它首先不应该编译,为什么会发生这种情况,不应该快速观察异常?

EDIT2:

好吧,快速观看也适用于副本ms,这就是为什么我可以编辑它的价值,它实际上并没有改变它的内容MyPrivateVariable.

Joe*_*ton 14

你正在使用它们作为可变结构.避免这样做:

为什么可变结构"邪恶"?


Roh*_*ith 6

Struct具有值类型语义.因此,对struct实例所做的任何修改都不会影响原始实例.C#编译器试图警告你这一点.


bur*_*tar 5

C#不会在"foreach(MyStruct ms ...)"中通过引用迭代结构,因此该上下文中的ms是不可变的.

用类替换MyStruct.

QuickWatch可以操作堆栈上的值类型.