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