我需要了解一些关于F#非常重要的事情:它如何处理引用和值。 我知道F#定义了不可变和可变对象,也知道了原因。
但有一件事我不知道:对象是如何处理的?
我的意思是,在C#中,一切都是一个指针,当为一个对象分配另一个的引用时,数据是相同的,我们将有两个指向相同数据的指针。
所以在C#中如果我有这个:
Object myobj1 = new Object();
Object myobj2 = myobj1;
bool myobj1 == myobj2; // It is true
那么,f#怎么样?
let myvar: MyObj = new MyObj ()
let myvar2: MyObj = myvar
这里的情况如何? 作业是否涉及复制?或不。
而且,一般来说,这个主题的f#方法是什么? (我的意思是价值与参考)。
答案 0 :(得分:7)
使用引用类型和值类型时,F#的行为与C#类似。
Struct
属性声明)时,唯一值得注意的区别是标准F#类型(有区别的联合,记录,列表,数组和元组)具有结构相等语义。这意味着它们通过比较存储在它们中的实际值而不是通过比较引用(即使它们是引用类型)进行比较。例如,如果您创建两个包含相同数据的元组列表:
> let l1 = [ ("Hello", 0); ("Hi", 1) ]
let l2 = [ ("Hi", 1); ("Hello", 0) ] |> List.rev;;
(...)
> l1 = l2;;
val it : bool = true
即使列表和元组是引用类型,也会得到true
。但是,如果比较参考文献(编辑:添加样本灵感来自kvb ):
> System.Object.ReferenceEquals(l1, l2);;
val it : bool = false
使用结构相等在F#中是有意义的,因为类型是不可变的 - 当您创建包含相同数据的两个值时,它们将始终相同。如果它们是可变的,你可以改变它们并且它们将不再相等 - 这就是为什么使用引用相等来为可变类型更有意义。
答案 1 :(得分:6)
您可以通过以下简单的实验说服自己,F#的行为与C#的行为相同:
printfn "%b" (myvar = myvar2) // true
或者更好:
printfn "%b" (obj.ReferenceEquals(myvar, myvar2)) // true
因为Tomas指出,(=)
的行为可能有点微妙。
从我的角度来看,没有任何合理的选择; myvar2
可能还包含哪些内容?复制任意类型的对象没有任何通用机制,因此唯一有意义的行为是myvar
和myvar2
包含相同的引用。