F#处理值和引用

And*_*dry 2 .net f# reference

我需要了解一些关于F#非常重要的事情:它如何处理引用和值.我知道F#定义了不可变和可变对象,也知道了原因.

但有一件事我不知道:对象是如何处理的?

我的意思是,在C#中,一切都是指针,当为一个对象分配另一个的引用时,数据是相同的,我们将有两个指向相同数据的指针.

所以在C#中如果我有这个:

Object myobj1 = new Object();
Object myobj2 = myobj1;
bool myobj1 == myobj2; // It is true
Run Code Online (Sandbox Code Playgroud)

那么,f#怎么样?

let myvar: MyObj = new MyObj ()
let myvar2: MyObj = myvar
Run Code Online (Sandbox Code Playgroud)

这是什么情况?作业是否涉及复制?或不.

而且,一般来说,这个主题的f#方法是什么?(我的意思是价值与参考).

Tom*_*cek 7

使用引用类型和值类型时,F#的行为与C#类似.

  • 如果您有引用类型,它将使用对堆中实例的引用.
  • 当您具有值类型(内置,在C#中声明或在F#中使用Struct属性声明)时,
    将值分配给另一个值或作为参数传递时复制该值.

唯一值得注意的区别是标准F#类型(有区别的联合,记录,列表,数组和元组)具有结构相等的语义.这意味着它们通过比较存储在它们中的实际值而不是通过比较引用(即使它们是引用类型)进行比较.例如,如果您创建两个包含相同数据的元组列表:

> let l1 = [ ("Hello", 0); ("Hi", 1) ]
  let l2 = [ ("Hi", 1); ("Hello", 0) ] |> List.rev;;
(...)

> l1 = l2;;
val it : bool = true
Run Code Online (Sandbox Code Playgroud)

true即使列表和元组是引用类型,也会得到.但是,如果你比较参考文献(编辑:添加样本灵感来自kvb):

> System.Object.ReferenceEquals(l1, l2);;
val it : bool = false
Run Code Online (Sandbox Code Playgroud)

在F#中使用结构相等是有意义的,因为类型是不可变的 - 当您创建包含相同数据的两个值时,它们将始终相同.如果它们是可变的,你可以改变它们并且它们将不再相等 - 这就是为什么使用引用相等来为可变类型更有意义.

  • @Andry:原则上它并不重要 - 因为它们是不可变的并且具有结构相等的语义,它们的行为会相同.从实际的角度来看,它可能很重要(为了表现).所以,答案是所有标准F#类型都是引用类型.您可以通过将`[<Struct>]`添加到对象类型声明来定义值类型,但是有区别的联合将始终是引用类型. (3认同)

kvb*_*kvb 6

正如您可以通过以下简单实验说服自己,F#的行为与C#的行为相同:

printfn "%b" (myvar = myvar2)  // true
Run Code Online (Sandbox Code Playgroud)

或者更好的是:

printfn "%b" (obj.ReferenceEquals(myvar, myvar2)) // true
Run Code Online (Sandbox Code Playgroud)

因为托马斯指出,行为(=)可能有点微妙.

从我的角度来看,没有任何合理的选择; 还有什么myvar2可能含有?没有用于复制任意类型的对象任何一般性机制,这样才有意义的唯一行为是myvarmyvar2含有相等引用.