F#中不允许写入结构记录的可变属性。为什么?

F#中不允许写入结构记录的可变属性。为什么?,f#,F#,当我有以下代码时: [<Struct>] type Person = { mutable FirstName:string ; LastName : string} let john = { FirstName = "John"; LastName = "Connor"} john.FirstName <- "Sarah"; [] 类型Person={mutable FirstName:string;LastName:string} 让john={FirstName=“j

当我有以下代码时:

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

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

john.FirstName <- "Sarah";
[]
类型Person={mutable FirstName:string;LastName:string}
让john={FirstName=“john”;LastName=“Connor”}

john.FirstName这可以保护您免受几年前困扰
C
世界的陷阱:结构是按值传递的

请注意,红色的波形(如果您在IDE中)不会出现在
FirstName
下,而是出现在
john
下。编译器抱怨的不是更改
john.FirstName
的值,而是更改
john
本身的值

对于非结构,引用和被引用对象之间有一个重要的区别:

引用和对象本身都是可变的。这样,您既可以修改引用(即使其指向不同的对象),也可以修改对象(即更改其字段的内容)

但是,对于结构,这种区别并不存在,因为没有引用:

这意味着当你变异
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
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!
我清楚地记得几乎每天都回答这个问题。那些日子真是太好了!:-)

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