我正在尝试将字符串中的泛型转换运算符定义为Enum,我想像这样使用它:
let day = asEnum<DayOfWeek>("Monday")
但是有了这个实现:
let asEnum<'a, 'b when 'a: (new : unit -> 'a) and 'a : struct and 'a :> ValueType and 'a : enum<'b>> text =
match Enum.TryParse<'a>(text) with
| true, value -> Some value
| false, _ -> None
我只能这样使用它:
let day = asEnum<DayOfWeek,_>("Monday")
或者这个:
let day:DayOfWeek option = asEnum("Monday")
如果我从类型约束中完全省略'a : enum<'b>
,我可以按照我的意愿使用它,但如果有人没有指定类型,它将默认为int
,我真的不喜欢不喜欢,我更喜欢它给出一个编译时错误,就像我指定一个约束
也许有任何技巧只能指定一个类型参数并让另一个参与?有什么想法吗?
答案 0 :(得分:3)
这个怎么样?
let asEnum s :'a option when 'a:enum<'b> =
match System.Enum.TryParse s with
| true, v -> Some v
| _ -> None
// works, but warns that type params shouldn't be given explicitly
asEnum<System.Reflection.BindingFlags,_> "DeclaredOnly"
// also okay
(asEnum "DeclaredOnly" : System.Reflection.BindingFlags option)
答案 1 :(得分:2)
不幸的是,为了增加约束,似乎你必须全部拼出:(正如kvb指出的那样,你可以通过添加{来避免重复TryParse
上的约束。 {1}}尖括号外的约束)
这也有效:
'T : enum<int>
如果基础类型不是let asEnum<'T
when 'T : enum<int>
and 'T : struct
and 'T :> ValueType
and 'T : (new : unit -> 'T)> text =
match Enum.TryParse<'T>(text) with
| true, value -> Some value
| _ -> None
:
int
答案 2 :(得分:0)
我尝试过的另一件事是:
type AsEnum =
static member Get<'a, 'b when 'a: (new : unit -> 'a) and 'a : struct and 'a :> ValueType and 'a : enum<int>> (text:string) =
match Enum.TryParse<'a>(text) with
| true, value -> Some value
| _ -> None
static member Get<'a, 'b when 'a: (new : unit -> 'a) and 'a : struct and 'a :> ValueType and 'a : enum<int64>> (text:string) =
match Enum.TryParse<'a>(text) with
| true, value -> Some value
| _ -> None
let a = AsEnum.Get<BindingFlags>.Get "DeclaredOnly"
尝试查看是否可以让编译器推断出要调用的重载,但是如果失败则会出现歧义错误
答案 3 :(得分:0)
3年后的一些更新^ _ ^
使用此字符串扩展名将字符串转换为枚举
type System.String with
/// Strongly-typed shortcut for Enum.TryParse().
member this.ToEnum<'a when 'a :> System.Enum and 'a : struct and 'a : (new: unit -> 'a)> () =
let ok, v = System.Enum.TryParse<'a>(this, true)
if ok then Some v else None
小心你的枚举声明。
type failingEnum =
| FirstValue
| SecondValue
| AnotherValue
type compliantEnum =
| FirstValue = 0
| SecondValue = 1
| AnotherValue = 2
然后
let x = "whatever".ToEnum<failingEnum>();
//- will give error failingEnum is not compatible with the type System.Enum
let x = "whatever".ToEnum<compliantEnum>();
//- will succeed !