F# 转换运算符
F# Casting Operators
以下 F# 转换运算符之间有什么区别?我似乎无法理解它们为什么以及如何不同。
(type) X
X :> type
X :?> type
第一个不是 F# 中的强制转换,但如果您习惯了 C#,它可能看起来像一个。但这实际上是在调用类型转换 function(如 int
),括号实际上并不是必需的(而且可能会使一切变得更加混乱)。
(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
请注意,这适用于基本类型,因为有预定义的转换函数,但不适用于任意类型:
(bigint) 1 // no such conversion function, so this is a compile-time error
其他两者之间的区别在于:>
执行向上转换(从类型到超类型,这总是安全的)而:?>
执行向下转换(从类型到子类型,这可能会失败,因此中间的 '?'
)。
还有命名为 upcast
和 downcast
的运算符,它们的用法类似:
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)
在某些情况下,可以成功推断出向上转型或向下转型的目标类型,在这种情况下,使用 upcast
或 downcast
运算符时不需要类型注释,而你总是需要为 :>
或 :?>
运算符提供类型参数(尽管如果您希望推断它,您可以提供 _
):
List.map (fun x -> x + 1) (downcast (box [1]))
List.map (fun x -> x + 1) (box [1] :?> _)
以下 F# 转换运算符之间有什么区别?我似乎无法理解它们为什么以及如何不同。
(type) X
X :> type
X :?> type
第一个不是 F# 中的强制转换,但如果您习惯了 C#,它可能看起来像一个。但这实际上是在调用类型转换 function(如 int
),括号实际上并不是必需的(而且可能会使一切变得更加混乱)。
(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
请注意,这适用于基本类型,因为有预定义的转换函数,但不适用于任意类型:
(bigint) 1 // no such conversion function, so this is a compile-time error
其他两者之间的区别在于:>
执行向上转换(从类型到超类型,这总是安全的)而:?>
执行向下转换(从类型到子类型,这可能会失败,因此中间的 '?'
)。
还有命名为 upcast
和 downcast
的运算符,它们的用法类似:
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)
在某些情况下,可以成功推断出向上转型或向下转型的目标类型,在这种情况下,使用 upcast
或 downcast
运算符时不需要类型注释,而你总是需要为 :>
或 :?>
运算符提供类型参数(尽管如果您希望推断它,您可以提供 _
):
List.map (fun x -> x + 1) (downcast (box [1]))
List.map (fun x -> x + 1) (box [1] :?> _)