我想将几十个枚举类型的字符串表示转换为枚举值。 将字符串转换为具体类型很容易:
Enum.Parse(typeof<FontStyle>,"Bold") |> unbox<FontStyle>
但是现在我想写函数,其中type和string是参数。 我能写的最好的是:
> let s2e (_: 'a) s = Enum.Parse(typeof<'a>,s) |> unbox<'a>;;
val s2e : 'a -> string -> 'a
> s2e FontStyle.Regular "Bold";;
val it : FontStyle = Bold
有没有选择写这样的东西但是将类型本身作为第一个参数?
答案 0 :(得分:4)
该函数需要采用单个类型参数,该参数将是返回的枚举的类型。但是,您不需要使用代码中未使用的“伪”参数来指定类型 - 您可以使用相同的表示法调用函数时指定实际的类型参数,例如在调用{{1 }}。
以下修改的函数采用仅在返回类型中出现的单个类型参数(为了避免混淆SO代码格式化程序,我在代码中替换了'with':
defaultof<SomeType>
调用函数时,需要明确指定类型:
> let parseEnum<´a> s = Enum.Parse(typeof<´a>,s) |> unbox<´a>;;
val parseEnum : string -> ´a
您的解决方案与此非常接近 - 唯一的变化是您可以显式指定类型参数,而不是提供见证值来指导类型推断。
答案 1 :(得分:1)
enum
约束来防止使用无意义的类型参数:
let parseEnum<'t,'u when 't:enum<'u>> s = System.Enum.Parse(typeof<'t>, s) :?> 't
(parseEnum "Class" : System.AttributeTargets)
现在调用(parseEnum "Test" : int)
将在编译时失败,因为int
不是枚举。
修改强>
由于我们实际上没有对基础类型'u
执行任何操作,因此我们不需要F#的枚举约束的全部功能,因为ssp在注释中指出。这更容易使用,因为它只有一个类型参数:
let parseEnum<'t when 't :> System.Enum and 't : struct> s =
System.Enum.Parse(typeof<'t>, s) :?> 't
请注意,struct
约束会阻止使用System.Enum
本身作为类型参数。