2014-09-26 105 views
7

好吧,讓我們有一些代碼:的IList <mutable_struct> VS mutable_struct []

//I complie nicely 
ValueType[] good = new ValueType[1]; 
good[0].Name = "Robin"; 

//I don't compile: Cannot modify expression because its not a variable 
IList<ValueType> bad = new ValueType[1]; 
bad[0].Name = "Jerome"; 

struct ValueType 
{ 
    public string Name; 
} 

什麼恰恰是怎麼回事,導致該編譯器卻步幕後?

//Adding to watch the following 
good.GetType().Name //Value = "ValueType[]" It's a ValueType array. 
bad.GetType().Name //Value = "ValueType[]" Also a ValueType array. 

編譯器阻止我修改要更改的對象副本的成員。但爲什麼從這個數組中創建一個副本?

多一點研究牽扯出:

var guess = (ValueType[]) bad; 
guess[0].Name="Delilah"; 

現在,你有什麼感想bad[0].Name是什麼?沒錯,這是「Delilah」。

+1

編譯器很慷慨,它會阻止你修改'Name'的副本。看看[修改字典中的結構變量](http://stackoverflow.com/questions/6255305/modify-struct-variable-in-a-dictionary) – 2014-09-26 13:30:27

+0

@YuvalItzchakov是的,它是非常有用的。爲什麼在第二種情況下複製,而不是在第一種情況下複製? – Robino 2014-09-26 13:31:01

+0

您鏈接到我的qn已經upvoted。但是,它非常明顯地創建了一個值類型的副本。在我的例子中,它感覺有點微妙。 – Robino 2014-09-26 13:33:31

回答

7

爲什麼值類型與所述IList<ValueType>複製返回而不是從陣列

因爲數組是編譯器知道的一個內置的構建體。它的運算符[]具有內置語義,它在數組本身內爲編譯器提供可修改的引用。

另一方面,當編譯器處理一個接口時,它知道它返回了一個值類型的副本,該值正在嘗試修改。換句話說,編譯器以不同方式查看IList的運算符[]和數組的運算符[]

注意:不用說,這個練習純屬學術價值,因爲mutable structs are evil

+0

流行的可變引用類型同樣很糟糕,只是方式稍有不同。 – CodesInChaos 2014-09-26 13:54:47