2017-07-03 88 views

回答

13

這可以保護您免受前幾年瘟疫C#世界的困擾:結構按值傳遞

請注意,紅色波浪狀(如果您在IDE中)不在FirstName之下,但不在john之下。編譯器不抱怨改變john.FirstName的值,而是改變john本身的值。

對於非結構中,在參考和引用的對象之間一個重要的區別:

enter image description here

參考和對象本身可以是可變的。所以你可以改變引用(即使它指向一個不同的對象),或者你可以改變對象(即改變它的字段的內容)。

對於結構,但是,這種區別不存在,因爲沒有參考:

enter image description here

這意味着,當你發生變異john.FirstName,還發生變異john本身。他們是一樣的。

因此,爲了執行此突變,你需要聲明john本身作爲可變太:

[<Struct>] 
type Person = { mutable FirstName:string ; LastName : string} 

let mutable john = { FirstName = "John"; LastName = "Connor"} 

john.FirstName <- "Sarah" // <-- works fine now 

爲了進一步說明,嘗試在C#:

struct Person 
{ 
    public string FirstName; 
    public string LastName; 
} 

class SomeClass 
{ 
    public Person Person { get; } = new Person { FirstName = "John", LastName = "Smith" }; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var c = new SomeClass(); 
     c.Person.FirstName = "Jack"; 
    } 
} 

IDE將幫助下劃線c.Person並告訴您,您的「無法修改返回值'SomeClass.Person',因爲它不是一個變量「

這是爲什麼?每次你寫c.Person時,這被翻譯成調用屬性getter,就像另一種返回你的方法Person。但由於Person通過值傳遞,返回Person將是不同的每次Person。 getter不能返回你對同一個對象的引用,因爲不能引用一個結構體。因此,對此返回值所做的任何更改都不會反映在SomeClass內的原始Person中。

存在這是很有幫助的編譯器錯誤之前,很多人都這樣做:

c.Person.FirstName = "Jack"; // Why the F doesn't it change? Must be compiler bug! 

我清楚地記得,幾乎每天都在回答這個問題。那些日子!:-)

相關問題