F# 铸造运算符

Posted

技术标签:

【中文标题】F# 铸造运算符【英文标题】:F# Casting Operators 【发布时间】:2015-10-15 11:51:29 【问题描述】:

以下 F# 强制转换运算符有什么区别?我似乎无法理解它们为什么以及如何不同。

(type) X
X :> type
X :?> type

【问题讨论】:

这只涵盖Upcast和Downcast。 【参考方案1】:

第一个不是 F# 中的强制转换,但如果您习惯 C#,它可能看起来像一个。但这实际上是在调用类型转换函数(如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

另外两者的区别在于:> 执行向上转型(从类型到超类型,这总是安全的),:?> 执行向下转型(从类型到子类型,这可能会失败,因此 @ 987654326@在中间)。

还有命名为upcastdowncast 的运算符可以以类似的方式使用:

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)

在某些情况下,向上转换或向下转换的目标类型可能会被成功推断,在这种情况下,使用 upcastdowncast 运算符时不需要类型注释,而您始终需要提供类型:>:?> 运算符的参数(尽管您可以提供 _ 如果您希望它被推断):

List.map (fun x -> x + 1) (downcast (box [1]))
List.map (fun x -> x + 1) (box [1] :?> _)

【讨论】:

那些感觉与逻辑相反(我总是对子类型箭头感到困惑:/)。他们是对的?猜猜这是语法限制。 有什么东西可以将obj 转换为具有特定运算符可用的东西,例如*?我知道您可以通过具有相当复杂的代码<'T when 'T : (static member (+) : ^T * ^T -> ^T)> 来制定通用约束来做到这一点,但是有没有办法将其转换为那个? @DanRayson - 不,但您可以使用标准 .NET 反射来调用这样的方法,而无需执行强制转换。

以上是关于F# 铸造运算符的主要内容,如果未能解决你的问题,请参考以下文章

C# 类型转换

Java Class.cast()与强制转换运算符

在 C# 中定义 F# '**' 运算符

为啥 F# 有一个一元加号运算符?

F#中的空合并运算符?

无法在 F# 中重载布尔运算符