【问题标题】:How to use overloaded explicit conversion operators?如何使用重载的显式转换运算符?
【发布时间】:2016-06-02 15:28:17
【问题描述】:

我在 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
}

在 F# 中,如果我想从 long 创建它,我发现的唯一方法是:

let l = F.op_Explicit 3L

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

let inline f a = F.op_Explicit a

但这不能编译。我还尝试了成员约束:

let inline f (x:^a) = (F: (static member op_Explicit : ^a -> F) x) 

这也不编译。

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

顺便说一句,它确实在相反的方向上很好地工作:

let f = someF |> int64 // calls the right conversion operator

【问题讨论】:

    标签: f#


    【解决方案1】:

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

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

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

    【讨论】:

    • 太棒了!我唯一担心的是警告:“名称为‘op_Explicit’的成员约束被 F# 编译器赋予特殊状态,因为某些 .NET 类型通过该成员隐式扩充。如果您尝试调用,这可能会导致运行时失败来自您自己的代码的成员约束。”我可以放心地忽略它吗?
    • @Asik - 在这种情况下,您可以忽略它。该限制适用于某些情况,即编译器的行为就像存在 op_Explicit 一样,即使那里实际上并不存在。例如,如果您从我的答案中提取 g 到它自己的定义中,调用 (g 1 : int64) 将编译(因为编译器假装存在从 int 到 int64 的显式转换),但在运行时会失败(因为在现实;转换通常由执行环境本身处理)。
    猜你喜欢
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多