如何使用重载的显式转换运算符?

Asi*_*sik 6 f#

我有一个在C#中定义的类型,如下所示:

struct F {
    public static explicit operator F(long value) {}
    public static explicit operator long(F value) {}
    public static explicit operator F(double value) {}
    public static explicit operator double(F value) {}
    // more conversion operators
}
Run Code Online (Sandbox Code Playgroud)

在F#中,如果我想从长时间创建它,我找到的唯一方法是:

let l = F.op_Explicit 3L
Run Code Online (Sandbox Code Playgroud)

我尝试创建一个内联函数来使这更好:

let inline f a = F.op_Explicit a
Run Code Online (Sandbox Code Playgroud)

但这不编译.我也试过一个成员约束:

let inline f (x:^a) = (F: (static member op_Explicit : ^a -> F) x) 
Run Code Online (Sandbox Code Playgroud)

而这也不会编译.

是否可以定义一个函数或运算符来选择正确的过载?

另一方面,它在相反的方向上运行良好:

let f = someF |> int64 // calls the right conversion operator
Run Code Online (Sandbox Code Playgroud)

kvb*_*kvb 6

在单个具体类型上具有成员约束是无效的; 但是,这可能对你有用:

let inline f (x:^a) : F =
    let inline g x = ((^b or ^c):(static member op_Explicit : ^b -> ^c) x)
    g x
Run Code Online (Sandbox Code Playgroud)

这有一个更通用的类型f : ^a -> F when ( ^a or F) : (static member op_Explicit : ^a -> F),这是一种不可能手动注释任何值的类型!

  • @Asik - 在这种情况下你可以忽略它.这种限制适用于某些情况,即编译器的行为就好像存在op_Explicit,即使那里没有真正的op_Explicit.例如,如果你从我的答案中提取`g`到它自己的定义中,调用`(g 1:int64)`将编译(因为编译器假装有一个从int到int64的显式转换),但是会在运行时失败(因为实际上没有这样的成员;转换通常由执行环境本身处理). (2认同)