2010-09-24 41 views
3
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內容。

+0

什麼是編譯器錯誤? – 2010-09-24 19:18:51

+0

編譯器消息說什麼? – CodingGorilla 2010-09-24 19:19:01

+0

什麼是編譯器錯誤信息? – EJC 2010-09-24 19:19:02

回答

6

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

5

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

用類代替MyStruct。

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

+0

有時候在一個簡單的暴露字段'Holder '類中包裝一個可變結構對於在某些情況下使用是有用的,但僅僅用一個可變類替換一個可變結構以促進集合中事物的變異是一個壞主意。一般來說,每個可變對象應該只有一個封裝其可變狀態的其他對象。如果想從一個List >複製到另一個List中的某個地方,那麼List2 [1] .Value = List1 [3] .Value;'。要追加一個列表項到另一個列表中,說'List2.Add(new Holder (List1 [3]))''。 – supercat 2012-09-17 23:56:40

1

這是因爲結構是valuetype而不是引用類型。如果MyStruct是一個沒有問題編譯的類。詳情請查詢this線程。

0

您無法更改迭代變量引用的內容:也就是說,您無法將該變量指向其他實例(要找出原因,請參閱Why is The Iteration Variable in a C# foreach statement read-only?)。

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

MyFunction(ms)調用編譯,因爲它副本ms操作(雖然它仍然不會做你所期望的)。

+0

那麼爲什麼我可以在Quick Watch中修改它們?沒關係,那也適用於結構的副本,呃爲什麼結構還存在? – bevacqua 2010-09-24 19:28:07

+1

@Nico:結構有一個目的,但*可變*結構幾乎從來沒有做過。 – 2010-09-24 19:30:08

+1

@Nico:你正在做的是修改一個副本,然後扔掉。它本質上是一個沒有操作。 – 2010-09-24 20:40:41