8

文字列から列挙型への汎用変換演算子を定義しようとしていますが、次のように使用したいと思います。

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。これは本当に好きではありません。コンパイルすることをお勧めします制約を指定したときのような時間エラー

1 つの型パラメーターを指定するだけで、もう 1 つの型パラメーターを推論させるトリックがあるのではないでしょうか? 何か案は?

4

4 に答える 4

4

残念ながら、制約を強化するには、すべてを綴る必要があるようです: (kvbが指摘したように、山括弧の外側に制約TryParseを追加することで、制約の重複を避けることができます)'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

type ByteEnum =
  | None = 0uy

asEnum<ByteEnum> "None" //ERROR: The type 'int' does not match the type 'byte'
于 2013-02-27T15:02:08.747 に答える
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)
于 2013-02-27T15:49:28.520 に答える
1

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    

enum 宣言には注意してください。

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 !
于 2016-01-27T07:40:46.930 に答える
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"   

どのオーバーロードを呼び出すかをコンパイラに推測させることができるかどうかを確認しようとしましたが、あいまいなエラーで失敗した場合

于 2013-02-27T16:28:48.503 に答える