I am trying to process the contents of a dictionary based on the type of contained element (String, Int, Datetime etc). The following is a small test snippet which loads some test data and then extracts by type.
However I get the following constraint mismatch error which I don't understand - any ideas?
Error Info:
unmapdict.fsx(29,23): error FS0193: Type constraint mismatch.
The type 'String' is not compatible with the type 'Type'
open System
open System.Collections.Generic
// Type for dict entries
type dStruct = {
ftype: Type;
fvalue:obj;
}
let main() =
printfn "\n>>>>>> Extract Dictionary Elements <<<<< \n"
let ddict = new Dictionary<string, dStruct>()
let str = "String Data"
let rstring = { ftype=str.GetType(); fvalue=str ;}
ddict.Add("String", rstring)
let intn = 999
let rint32 = { ftype=intn.开发者_StackOverflowGetType(); fvalue=intn ;}
ddict.Add("Int32", rint32)
let rdatetime = {ftype=System.DateTime.Now.GetType(); fvalue=System.DateTime.Now}
ddict.Add("DateTime", rdatetime)
// Extract dict value elements; emumerate data types
ddict
|> Seq.map ( fun (KeyValue(k,v)) -> v)
|> Seq.iter (fun v ->
// Error occurs here >>
match v.ftype with
| :?System.String -> printfn "String Found ";
| :?System.Int32 -> printfn "Integer Found ";
| :?System.DateTime -> printfn "DateTime Found ";
|_ -> printfn "Unmatched Element"
// printfn "Dict: ftype: %A; fvalue: %A" v.ftype v.fvalue
)
printfn "\n>>>>>> F# Done <<<<< \n"
main()
Since .NET objects carry their types with them, I don't see any point to the dStruct
type (which is misleadingly named anyway, since it's not a struct). On a related note, your type test patterns (:? string
, etc.) don't work because you're testing an instance of class Type
against them, when you should be testing the instance that you actually care about. That is:
let main() =
printfn "\n>>>>>> Extract Dictionary Elements <<<<< \n"
let ddict = new Dictionary<string, obj>()
let str = "String Data"
ddict.Add("String", str)
let intn = 999
ddict.Add("Int32", intn)
ddict.Add("DateTime", System.DateTime.Now)
// Extract dict value elements; emumerate data types
ddict
|> Seq.map ( fun (KeyValue(k,v)) -> v)
|> Seq.iter (fun v ->
match v with
| :?System.String as s -> printfn "String Found: %s" s;
| :?System.Int32 as i -> printfn "Integer Found: %i" i;
| :?System.DateTime as dt -> printfn "DateTime Found: %A" dt;
|_ -> printfn "Unmatched Element"
)
printfn "\n>>>>>> F# Done <<<<< \n"
main()
A .NET Type
as returned by GetType
is not the same as a class. Instead, it is an instance of class Type
. Also, Type
cannot be used in pattern matching (unless we define special active patterns), but we can compare for equality.
If you change your code like this, it will work:
if v.ftype = typeof<String> then printfn "String Found "
elif v.ftype = typeof<System.Int32> then printfn "Integer Found "
elif v.ftype = typeof<System.DateTime> then printfn "DateTime Found "
else printfn "Unmatched Element"
精彩评论