无法更新结构中的可变字段?

Can't Update Mutable Field in Struct?

谁能告诉我为什么这个 Counter 结构不起作用?它总是在调用 Incr.

之间将值重置为 0
type Counter = 
    struct

        val mutable i: int 

        member public this.Incr() =
            this.i <- this.i + 1

        member public this.Count = 
            this.i
    end

let noCounty(s:string): int = 
    let x = new Counter()
    x.Incr()
    x.Incr()
    x.Count

我不知道为什么它不能按照你的方式工作,但它是这样工作的:

type Counter() = 
    [<DefaultValue>]
    val mutable i: int

    member public this.Incr() =
        this.i <- this.i + 1

    member public this.Count = 
        this.i

可变结构的语义总是令人困惑,因为在某些情况下,当您以某些方式使用它时,结构会被意外复制 - 因此最好避免结构内部发生变化。

您可以通过将 noCounty 中的 x 变量标记为可变来使它起作用。鉴于您当前对 Counter 的定义,以下内容按预期工作:

let noCounty() = 
    let mutable x = new Counter()
    x.Incr()
    x.Incr()
    x.Count

我同意这很令人困惑。我认为逻辑是,如果您将变量定义为不可变的,那么编译器会在进行任何可能改变它的调用之前将结构的值复制到一个新变量中。结果,编译后的代码看起来更像:

let noCounty () = 
    let x = new Counter()
    (let t1 = x in t1.Incr())
    (let t2 = x in t2.Incr())
    (let t3 = x in t3.Count)

我希望编译器能给我一些关于此的警告 - 所以在这种情况下缺少警告可能应该报告为编译器错误。 (虽然这种行为可能是有意的。)

如果你真的想这样做,你可以:

[<Struct>]
type Counter = 
        val mutable i: int 

        member public this.Incr() =
            this.i <- this.i + 1

        member public this.Count = 
            this.i

let  mutable x = Counter() // You need to make the struct itself mutable
x.Incr()
x.Incr()
x.Count
//val it : int = 2

老实说,编译器应该抱怨这种行为。虽然在一般情况下进行变异并不是一个好主意,特别是在结构中;你可以,但你需要使 x 本身可变,因为你正在改变结构本身,它是一种值类型。另一个答案给你一个 class,这是一个引用类型。