2015-07-01 2 views
2

Я пытаюсь создать примитивные значения с учетом типа в F #. Код приведен ниже, но он не работает. Буду признателен за всю помощь и благодарность заранее.отражение и сопоставление образцов в F #

open System 

let getvalue (t: Type) (v: string) : obj = 
    match box t with 
    | :? int -> let r = (int) v 
        box r 
    | :? byte -> let r = (byte) v 
        box r 
    | :? sbyte -> let r = (sbyte) v 
        box r 
    | :? int16 -> let r = (int16) v 
        box r 
    | :? uint32 -> let r = (uint32) v 
        box r 
    | :? int64 -> let r = (int64) v 
        box r 
    | :? uint64 -> let r = (uint64) v 
        box r 
    | :? double -> let r = (double) v 
        box r 
    | :? float32 -> let r = (float32) v 
        box r 
    | :? decimal -> let r = (decimal) v 
        box r 
    | :? char -> let r = (char) v 
        box r 
    | :? string -> v :> obj 
    | _ -> 
      let s = sprintf "Error unknown type %A" t 
      raise (ApplicationException(s)) 
+0

Как именно он не работает? Кроме того, как он использует отражение? –

+0

Он просто не попадает ни в один из шаблонов. –

+0

Когда вы задаете вопросы, никогда не пишите - «это не работает». Четко объясните проблему и желаемое поведение. –

ответ

3

t Так как это всегда значение Type, он будет никогда не быть типа int, byte, decimal и т.д. Это причина, по которой функция всегда вызывает исключение; эти другие матчи никогда не могут быть правдой.

Вместо этого, вы должны сравнить t с typeof<int>, typeof<byte> и т.д. Тем не менее, вы не можете использовать постоянный шаблон для этого, потому что typeof<int>, typeof<byte> и т.д., не являются постоянными.

Вместо этого, вы можете использовать if .. elif .. else выражение:

open System 

let getValue (t: Type) (v: string) : obj = 
    if t = typeof<int> then box ((int) v) 
    elif t = typeof<byte> then box ((byte) v) 
    elif t = typeof<sbyte> then box ((sbyte) v) 
    elif t = typeof<int16> then box ((int16) v) 
    elif t = typeof<uint32> then box ((uint32) v) 
    elif t = typeof<int64> then box ((int64) v) 
    elif t = typeof<uint64> then box ((uint64) v) 
    elif t = typeof<double> then box ((double) v) 
    elif t = typeof<float32> then box ((float32) v) 
    elif t = typeof<decimal> then box ((decimal) v) 
    elif t = typeof<char> then box ((char) v) 
    elif t = typeof<string> then v :> obj 
    else 
     let s = sprintf "Error unknown type %A" t 
     raise (ApplicationException(s)) 

Если вы действительно хотите использовать сопоставление с образцом, вы могли бы рассмотреть это скрывается позади active pattern, но лично я не думаю, что это будет быть стоящим.

+0

Спасибо, что это сработало. –

5

Не нужно изобретать велосипед, используйте Convert.ChangeType.

Если вы так склонны, вы можете написать обертку вокруг этого, чтобы компилятор автоматически определял типы.

let inline getValue<'a> (s:string) = // limit to string only if desired 
    System.Convert.ChangeType(s, typeof<'a>) :?> 'a 

let x = getValue "1" + 1.2 // no need to explicitly state "float" anywhere here 
printfn "%A" x     // 2.2 
Смежные вопросы