簡體   English   中英

在C#中Foreach結構奇怪的編譯錯誤

[英]Foreach struct weird compile error in C#

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 iteration variable'

編輯:

額外的問題:

我只是嘗試從MyFunction更改一個字符串,它實際上並沒有更新ms 但是:如果我去快速觀察並在那里分配相同的值,它會更新ms 如果它首先不應該編譯,為什么會發生這種情況,不應該快速觀察異常?

EDIT2:

好的,快速監視也適用於ms的副本,這就是為什么我可以編輯它的值,它實際上並沒有改變MyPrivateVariable的內容。

你正在使用它們作為可變結構。 避免這樣做:

為什么可變結構“邪惡”?

Struct具有值類型語義。 因此,對struct實例所做的任何修改都不會影響原始實例。 C#編譯器試圖警告你這一點。

C#不會在“foreach(MyStruct ms ...)”中通過引用迭代結構,因此該上下文中的ms是不可變的。

用類替換MyStruct。

QuickWatch可以操作堆棧上的值類型。

這是因為struct是valuetype而不是引用類型。 如果MyStruct是一個類,它將編譯沒有問題。 查看主題以獲取詳細信息

您無法更改迭代變量引用的內容:也就是說,您無法將變量指向另一個實例(要查明原因,請參閱為什么C#foreach語句中的迭代變量是只讀的? )。

'修改'結構(值類型)會創建該類型的新實例 ,因此語句ms.MyBool = false是沒有意義的。

MyFunction(ms)的調用進行編譯,因為它在ms 的副本上運行(盡管它仍然不會按照您的預期執行)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM