F#中严格的通用枚举转换

时间:2015-12-05 06:38:09

标签: generics enums f# inline

我想编写一个带有签名int -> 'TEnum的函数,如果目标枚举不包含输入值,它将抛出异常。这是我的第一次尝试:

let parseEnum<'TEnum when 'TEnum : enum<int>> (value : int) : 'TEnum =
    let enumType = typeof<'TEnum>
    if not <| Enum.IsDefined (enumType, value) then
        raise <| ArgumentException (sprintf "Invalid value of %A: %d" enumType value)

    enum value

编译器向我显示以下错误消息:“错误FS0001:由于在编译时无法解析类型参数,因此无法在此处使用声明的类型参数'TEnum'”(我认为这是因为enum具有附加约束的函数。)

嗯,好吧,我明白了这个问题。我将使用statically resolved type parameter。这是我的第二次尝试:

let inline parseEnum2 (value : int) : ^TEnum =
    let enumType = typeof<^TEnum>
    if not <| Enum.IsDefined (enumType, value) then
        raise <| ArgumentException (sprintf "Invalid value of %A: %d" enumType value)

    enum value

但是编译器仍然抱怨:“错误FS3156:意外的令牌'&gt;'或“不完整的表达”在第typeof<^TEnum>行。

我做错了什么?我怎么能写这个函数?

1 个答案:

答案 0 :(得分:6)

你需要在帽子之间留一个空间。签署ˆ<就像这样:

let enumType = typeof< ^TEnum>

事实上你不需要帽子,你可以写:

open System
let inline parseEnum2 value : 'TEnum =
    let enumType = typeof<'TEnum>
    if not <| Enum.IsDefined (enumType, value) then
        raise <| ArgumentException (sprintf "Invalid value of %A: %d" enumType value)

    enum value

因为在这种情况下会自动推断静态约束,所以当你真正需要编写“帽子”时,这是唯一的地方。是在手写静态约束时。