【问题标题】:Forcing a field of an F# type to be null强制 F# 类型的字段为空
【发布时间】:2012-01-03 01:36:26
【问题描述】:

我非常了解option 的好处,但在这种情况下,出于性能原因,我想避免使用optionoption 将一个类型包装在一个类中,这意味着垃圾收集器需要做更多的工作——我想避免这种情况。

尤其是在这种情况下,我有多个字段在相同的情况下都是Some,但我不想把它们放在一个元组中,因为元组也是类——并且对GC。所以我最终访问了field.Value——这违背了option的目的。

因此,除非有我不知道的优化导致option 类型被视为可能为空的引用,否则我只想使用null。有没有办法让我做到这一点?

编辑:为了扩展我正在做的事情,我正在制作一个bounding volume hierarchy,它实际上是一棵二叉树,数据仅在叶节点处。我将它作为一个类而不是作为一个受歧视的联合来实现,因为出于性能原因保持项目不可变不是一种选择,并且受歧视的联合不能有 mutable 成员,只有 refs - 再次,添加到 GC 压力。

虽然在函数式语言中很愚蠢,但我最终可能只是将每个节点类型都作为Node 父类型的继承。 Downcasting 并不是最快的操作,但就 XNA 和 WP7 而言,几乎任何事情都比激怒 GC 更好。

【问题讨论】:

  • 您确定增加的 GC 压力在您的情况下真的很重要吗?
  • @svick 是的,不幸的是,它用于 XNA 游戏的碰撞检测——这意味着它最终可能会在 WP7 或 Xbox 360 上运行,它们都有一代 GC。
  • "给 GC 带来了额外的压力。" - 你测量过这个吗?
  • @Mitch 不,但我已经测量了在粒子系统中使用元组对 GC 的影响。它非常难看,即使在 x64 .NET 4 上也是如此。切换到自定义结构元组会大大增加我可以模拟的粒子数量。
  • 我不能完全理解你想要做什么,但除了 null 或选项类型之外,可能还有其他方法。也许您可以详细说明您的用例,我们或许可以找到第三种方法。

标签: f# null option


【解决方案1】:

根据this MSDN documentation,如果您使用[<AllowNullLiteral>] 属性装饰您的类型,则可以调用Unchecked.defaultof<T>() 为您构建一个null。

这似乎是在 F# 中做你想做的唯一方法。否则,你可以编组到另一种 .net 语言并从那里得到空值......但我猜这根本不是你想要的

【讨论】:

  • 这要求消费者类型也被标记为[<AllowNullLiteral>],但我想这总比没有好。我的 4 个字段中的 3 个现在可以为空——左、右和父节点。
  • 实际上,我相信您误读了文档:在您拥有的类型上使用 [<AllowNullLiteral>] 以允许 null 作为正确的值。使用 Unchecked.defaultof<T>() 创建您不拥有的 F# 类型的 null 值,否则不允许 null 作为正确值(这意味着您还需要执行类似 object.ReferenceEquals(x, null) 而不是 x = null 之类的操作来解决编译器问题检查)。
  • @Stephen 是的,原来我只需要Unchecked.defaultof<T>
【解决方案2】:

现在有价值选项可以让你两全其美

[<StructuralEquality; StructuralComparison>]
[<Struct>]
type ValueOption<'T> =
    | ValueNone
    | ValueSome of 'T

没有类包装,Option&lt;'T&gt;的语法语义

【讨论】:

  • 这很酷。我的印象是 struct DUs 只能是单例。你碰巧知道这些东西的记忆表示是什么样的吗?它没有说in the docs
猜你喜欢
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多