Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Casting Operators

What is the difference between the following F# casting operators? I can't seem to understand why and how they are all different.

(type) X
X :> type
X :?> type
like image 811
user3685285 Avatar asked Jul 24 '15 17:07

user3685285


Video Answer


1 Answers

The first isn't a cast in F#, though if you're used to C# it might appear that it works like one. But this is actually invoking a type conversion function (like int), and the parentheses aren't actually required (and are just likely to make everything more confusing).

(int) "4" // the number 4 - this is a conversion, not a cast
int "4"   // same thing, but idiomatic
int "NaN" // compiles but throws an exception at runtime
(int) (box 4) // doesn't compile because int doesn't do downcasts, just known conversions

Note that this works for primitive types, because there are predefined conversion functions, but it won't work for arbitrary types:

(bigint) 1 // no such conversion function, so this is a compile-time error

The difference between the other two is that :> performs upcasts (from a type to a supertype, which is always safe) and :?> performs downcasts (from a type to a subtype, which might fail, thus the '?' in the middle).

There are also named upcast and downcast operators which can be used in a similar way:

5 :> obj                 // upcast int to obj
(upcast 5 : obj)         // same
(box 5) :?> int          // downcast an obj to int (successfully)
(downcast (box 5) : int) // same
(box "5") :?> int        // downcast an obj to int (unsuccessfully)

In some contexts the target type of the upcast or downcast may be successfully inferred, in which case you don't need the type annotations when using the upcast or downcast operators, while you always need to provide a type argument to the :> or :?> operators (though you can supply _ if you expect it to be inferred):

List.map (fun x -> x + 1) (downcast (box [1]))
List.map (fun x -> x + 1) (box [1] :?> _)
like image 80
kvb Avatar answered Oct 11 '22 02:10

kvb