从受歧视联合映射到枚举

Map from discriminated union to enum

目前,我正在尝试通过制作一个由 C# GUI 层和 F# 业务层组成的应用程序来自学一些 F#。在 GUI 层中,用户有时必须通过选择作为简单枚举一部分的值来做出选择,例如选择以下任一项:

enum {One, Two, Three}

我编写了一个函数来将枚举值转换为 F# 可区分联合

type MyValues = 
  | One
  | Two
  | Three

现在我不得不翻译回来,我已经厌倦了样板代码。有没有一种通用的方法可以将我的可区分联合转换为相应的枚举,反之亦然?

干杯,

您还可以在 F# 中定义枚举并完全避免进行转换:

type MyValues = 
  | One = 0
  | Two = 1
  | Three = 2

= <num> 位告诉 F# 编译器它应该将类型编译为联合。当使用 C# 中的类型时,这将显示为完全正常的枚举。唯一的危险是来自 C# 的人可以用 (MyValues)4 调用你的代码,这将编译,但如果你在 F# 中使用 match,它会导致不完整的模式匹配异常。

这里是通用 DU/enum 转换器。

open Microsoft.FSharp.Reflection

type Union<'U>() =
    static member val Cases = 
        FSharpType.GetUnionCases(typeof<'U>)
        |> Array.sortBy (fun case -> case.Tag)
        |> Array.map (fun case -> FSharpValue.MakeUnion(case, [||]) :?> 'U)

let ofEnum e = 
    let i = LanguagePrimitives.EnumToValue e
    Union.Cases.[i - 1]

let toEnum u = 
    let i = Union.Cases |> Array.findIndex ((=) u)
    LanguagePrimitives.EnumOfValue (i + 1)

let du : MyValues = ofEnum ConsoleColor.DarkGreen
let enum : ConsoleColor = toEnum Three

它将 DU 标记映射到枚举基础值。