【问题标题】:Why are MonoGame's Rectangle class fields immutable in F#?为什么 MonoGame 的 Rectangle 类字段在 F# 中是不可变的?
【发布时间】:2016-01-20 15:31:18
【问题描述】:
    let rect = new Rectangle(x, y, sprite.Width, sprite.Height)
    rect.X <- 888

第二行在 F# 中失败,但在 C# 中赋值有效。我不知道为什么。

【问题讨论】:

  • 以什么方式失败?矩形的全称是什么?我猜不是 System.Drawing 在完整的 .net 框架中的结构。
  • 这里有趣的是Rectangle 是一个结构,probably shouldn't be muttable 但它一直是并且一直是(在 MonoGame 和 XNA 中)。我认为 F# 有助于明确说明这里有问题,因为 C# 隐藏了问题。

标签: f# monogame


【解决方案1】:

Rectangle 是一个结构而不是一个类。如果您使用mutable 标记该值,则可以使该行按预期工作:

let mutable rect = new Rectangle(10, 21, 10, 21)
rect.X <- 888

这实际上很有趣,因为与 C# 相比,F# 使结构的值类型语义更加明显。

rect.X &lt;- 888 并没有真正改变字段,而是使用修改了 X 字段的结构的新值更新 rect。所以你可以想象它相当于rect &lt;- { rect with X = 888 }。到那时,编译器为什么想在那里看到mutable 就很清楚了。

我想知道为什么 F# 设计者不禁止结构的赋值语法,而是使用类似于记录语法的东西。可能他们不想让它与 C# 相比有太大的不同。

【讨论】:

    【解决方案2】:

    正如编译器可能说的那样,

    一个值必须是可变的才能改变内容或获取 值类型的地址,例如'让可变 x = ...'

    在 F# 中,let 创建一个不可变变量(即一个值)。编译器通过不允许您对其进行变异来强制执行此操作。您必须编写 let mutable 才能获得与 C# 中相同的变量声明。

    请注意,如果 Rectangle 是引用类型,F# 不会抱怨,因为您将修改值引用的内容,而不是值本身。对于值类型(如 Mono 的 Rectangle),绑定到该值的标识符就是该值本身,因此您不能对其进行变异。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      • 2010-12-14
      • 2018-03-05
      • 2013-03-04
      • 1970-01-01
      • 2015-05-25
      相关资源
      最近更新 更多