Matching on subtypes You can match on subtypes, using the :? operator, which gives you a crude polymorphism:
let x = new Object()
let y =
match x with
| :? System.Int32 ->
printfn "matched an int"
| :? System.DateTime ->
printfn "matched a datetime"
| _ ->
printfn "another type"
This only works to find subclasses of a parent class (in this case, Object). The overall type of the expression has the parent class as input.
Note that in some cases, you may need to “box” the value.
let detectType v =
match v with
| :? int -> printfn "this is an int"
| _ -> printfn "something else"
// error FS0008: This runtime coercion or type test from type 'a to int
// involves an indeterminate type based on information prior to this program point.
// Runtime type tests are not allowed on some types. Further type annotations are needed.
The message tells you the problem: “runtime type tests are not allowed on some types”. The answer is to “box” the value which forces it into a reference type, and then you can type check it:
let detectTypeBoxed v =
match box v with // used "box v"
| :? int -> printfn "this is an int"
| _ -> printfn "something else"
//test
detectTypeBoxed 1
detectTypeBoxed 3.14
In my opinion, matching and dispatching on types is a code smell, just as it is in object-oriented programming. It is occasionally necessary, but used carelessly is an indication of poor design.
In a good object oriented design, the correct approach would be to use polymorphism to replace the subtype tests, along with techniques such as double dispatch. So if you are doing this kind of OO in F#, you should probably use those same techniques.
如果“X”是不是字符串这将失败 - 我以为是这里真正的挑战。 –
除非绝对必要,否则在活动模式(出于性能原因)内使用try/catch是一个非常糟糕的主意。在这种情况下,您应该使用'System.Single.TryParse'来尝试解析该值,并且可以使用F#match语句的自动tupling功能来处理输出。 –
@JackP。很好,我会更新答案。 – MisterMetaphor