对类型中的静态字典感到困惑,在F#中

f#

使用这种类型:

type A =
    {
        S: string
    }

    static member private l = Dictionary<string, A>()
    static member add s = A.l.[s] <- { S=s }
    static member list () = l.Values

如果我做:

A.add "hello"
A.add "world"

我希望 A.list() 返回一些东西,因为字典是静态的,但它返回一个空列表。这是为什么?

为了澄清我正在尝试做的事情:我希望能够将类型 A 的对象注册到附加到类型本身的静态字典中,因为它会使对象存储库“自包含”在类型中, 在某种方式。

回答

l的不是一个字段,而是一个带有getter属性

与表象相反,“财产”并不是具有某种价值的记忆单元。“属性”是一对 get+set 函数。功能而已,仅此而已。没有记忆细胞。

所以你自己创建的是一个带有 getter(没有 setter)的属性,而 getter 所做的就是创建一个新的Dictionary并返回它。

这意味着,每次访问 时A.l,您都会得到一本全新的字典。因为l是一个功能,而不是一个记忆单元。

现在,为了制作一个记忆单元(又名“场”),人们通常会使用static member val,如下所示:

static member val private l = Dictionary<string, A>()

不幸的是,在这种特殊情况下,这不起作用,因为 F# 记录和联合中不允许使用静态字段。它们在实际类上运行良好,但不适用于 F# 类型。

因此,我建议将这些函数放在一个模块中,而不是使它们成为静态方法:

type A = { S: string }

module A =
  let private l = Dictionary<string, A>()
  let add s = l.[s] <- { S=s }
  let list () = l.Values

(一般来说:尝试使用更少的类和更多的模块和函数;它们在 F# 中更惯用,通常会导致更少的问题)

现在这按预期工作:

> A.add "hello";;
val it : unit = ()

> A.add "world";;
val it : unit = ()

> A.list();;
val it : Dictionary`2.ValueCollection<string,A> =
  seq [{ S = "hello" }; { S = "world" }]


以上是对类型中的静态字典感到困惑,在F#中的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>