Typecast matters are complicated in F#. Unlike many other languages, F# does not perform implicit upcasts by default. E.g. if class
Derived derives from
Base, and we have
let func( b : Base ) = ... let d : Derived = ...
func(d) will not work. The compiler will complain that type
Derived is not compatible with
Base. This comes as a shock to an object-oriented developer. We must explicitly “upcast” derived class to base class like this:
func (upcast d) or
func (d :> Base). In the former case, F# automatically figures out the destination type, in the latter case we explicitly say what it is.
Alternatively, we can explicitly declare
f as accepting a polymorphic argument:
let func( b : #Base ) = ...
I believe that internally this it implemented via generics. with actual argument type becoming a template parameter.
Overall, F# introduces five typecast operators:
||Automatically deduce destination type T from context and cast x to T. Static type of x must be a subtype of T, or the code will not compile.|
||Cast x to T. Static type of x must be a subtype of T, or the code will not compile.|
||no equivalent||Automatically deduce destination type T from context and cast x to T. Static type of x must be a base class of T, or the code will not compile.|
||If dynamic type of x is T or is derived from T, returns (T)x. Otherwise returns null, even if T is not a class type. Static type of x must be a base class of T, otherwise compilation error occurs.|
||Returns true if dynamic type of x is T or is derived from T, otherwise returns false. Static type of x must be a base class of T, or the code will not compile.|
In addition to the typecast operators, F# uses pattern matching operator
?: [as variable], e.g.
let func (x:Base) = match x with | :? TwiceDerived as td -> td_func td | :? Derived -> 10 | _ -> 0
* There are too many cast operators, and their spelling are quite confusing. I am afraid not many people can intuitively tell what a
:?> might mean.
* Polymorphism is applied inconsistently. E.g. it does not work in function calls by default, but it does work in the
:? operator. In the above example, if actual type of
:? Derived will still work