代码之家  ›  专栏  ›  技术社区  ›  bevacqua

c中的foreach结构奇怪的编译错误#

  •  3
  • bevacqua  · 技术社区  · 15 年前
    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;
            }
        }
    }
    

    对此有什么合理的解释吗?

    编译器返回:

    错误: 无法修改“ms”的成员,因为它是“foreach迭代” 变量'

    编辑:

    附加问题:

    我刚试着把一根绳子从 MyFunction ,它实际上没有更新 ms . 但是:如果我转到QuickWatch并在那里指定相同的值,它会更新 毫秒 . 如果它甚至不应该首先编译,那么为什么会发生这种情况呢?QuickWatch不应该抛出异常吗?

    编辑2:

    好的,快速观察也适用于 毫秒 这就是为什么我可以编辑它的值,它实际上不会改变 MyPrivateVariable .

    5 回复  |  直到 10 年前
        1
  •  14
  •   Community Mohan Dere    9 年前

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

    Why are mutable structs “evil”?

        2
  •  6
  •   Rohith    15 年前

    结构具有值类型语义。因此,对结构实例所做的任何修改都不会影响原始实例。C编译器正试图警告您这一点。

        3
  •  5
  •   burkestar    15 年前

    C不会在“foreach(mystruct-ms…”)中引用迭代结构,因此在该上下文中,ms是不可变的。

    将mystrut替换为类。

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

        4
  •  1
  •   Community Mohan Dere    9 年前

    这是因为结构是ValueType而不是引用类型。如果mystrut是一个类,它编译时就不会有问题。检查 this 线程获取详细信息。

        5
  •  0
  •   Community Mohan Dere    9 年前

    您不能更改迭代变量引用的内容:也就是说,您不能将变量指向不同的实例(要找出原因,请参见 Why is The Iteration Variable in a C# foreach statement read-only? )

    “modifying”结构(值类型)创建 新实例 类型,所以语句 ms.MyBool = false 毫无意义。

    呼叫 MyFunction(ms) 编译,因为它在 副本 属于 ms (尽管它仍然不能达到你所期望的效果)。