如何使用公共字段声明不可变结构?

时间:2013-08-08 19:19:28

标签: f#

我想在F#中写出这个C#的等价物:

struct Vector2 {
    public readonly int X;
    public readonly int Y;
    public Vector2(int x, int y) {
        X = x;
        Y = y;
    }
}

这会强制用户提供参数来创建实例[编辑:这对于值类型是错误的 - 所有值类型都有默认构造函数]。默认的Vector2也可以提供静态只读字段,即Vector2.Zero。

看起来获取公共字段的唯一方法是通过“val”关键字,但似乎不允许我使用默认构造函数初始化它们,我不希望有两个构造函数:

  [<Struct>]
  type MyInt(value) =
        val public Value : int = value;;

          val public Value : int = value;;
  -------------------------------^

stdin(7,32): error FS0010: Unexpected symbol '=' in member definition

我知道这可以通过成员绑定来完成,但如果我理解的话,这会创建属性,而不是字段。

2 个答案:

答案 0 :(得分:6)

根据此http://msdn.microsoft.com/en-us/library/vstudio/dd233233.aspx,可以将其作为

type Vector2 =
   struct 
      val public X: int
      val public Y: int
      new(x: int, y: int) = { X = x; Y = y }
   end

答案 1 :(得分:2)

如果F#Record适合您,那么这将有效:

type MyInt = {
    Value: int
};;

然后初始化:

let i = {Value=1};;

由于我不完全确定您的用例,我不确定这有多大帮助。

编辑: 对于它的价值,如果您更喜欢值类型的原因是您希望值类型相等语义,则记录支持(即使它们是引用类型)。考虑一下:

type Vector2 = {
     X:int;
     Y:int
};;

type Vector2 =
  {X: int;
   Y: int;}

let v = {X=1;Y=1};;

val v : Vector2 = {X = 1;
                   Y = 1;}

let v2 = {X=1;Y=1};;

val v2 : Vector2 = {X = 1;
                    Y = 1;}

v = v2;;
val it : bool = true

let v3 = {X=2;Y=2};;
v = v3;;
val it: bool = false

我的意思是说即使记录是引用类型,人们使用值类型(等同语义)的原因之一也不是记录的问题。尽管它是一种引用类型,但我相信它更接近你试图模仿的C#代码的行为 - 它的价值。