使用带有Explicit LayoutKind的F#Struct创建标记的联合

时间:2016-08-29 09:31:06

标签: f#

我试图创建一个F#等价的标记联合。我需要在应用程序代码的热路径中,有歧视的联合可能会导致过多的堆分配。

以下是例子:

    
[<Struct; StructLayout(LayoutKind.Explicit)>]
type Result =
    [<DefaultValue; FieldOffset 0>]
    val mutable IsAsync : bool
    [<DefaultValue; FieldOffset 1>] 
    val mutable Async : Async<obj>
    [<DefaultValue; FieldOffset 1>] 
    val mutable Sync : obj

但是,当我想为它提供某种创建方法时,问题就开始了。

示例1

static member Async(a:Async<obj>) = Result(IsAsync = true; Async=a)
static member Sync(s:obj) = Result(IsAsync = false; Sync=s)

抛出成员或对象构造函数&#39;结果&#39;取0参数但在此给出1.所需的签名是&#39; Result()&#39; 编译错误。

示例2

new(a:Async<obj>) = { IsAsync = true; Async = a; }
new(s:obj) = { IsAsync = false; Sync=s }

引发无关字段已被赋予值编译错误。

1 个答案:

答案 0 :(得分:5)

你有三个问题:

  1. 您需要使用逗号(,)分隔构造函数参数,而不是分号(;)。
  2. 对象引用必须在指针大小的边界上对齐。因此,在x64上,对象引用的偏移量必须为8。
  3. 静态和实例成员名称不应重叠。
  4. 这对我有用:

    [<Struct; StructLayout(LayoutKind.Explicit)>]
    type Result =
        [<DefaultValue; FieldOffset 0>]
        val mutable IsAsync : bool
        [<DefaultValue(false); FieldOffset 8>] 
        val mutable Async : Async<obj>
        [<DefaultValue; FieldOffset 8>] 
        val mutable Sync : obj
    
        static member MakeAsync(a:Async<obj>) = Result(IsAsync = true, Async=a)
        static member MakeSync(s:obj) = Result(IsAsync = false, Sync=s)