基本上有三种方法可以解决您的问题:
a) 您正在使用的类型已经支持您想要应用的运算符/方法。在这种情况下,只需在函数前面添加 "inline" 即可。
b) 您对所使用的类型具有完全控制权,即您可以在不使用扩展方法的情况下在函数定义中定义新成员。在这种情况下,您需要在每个实现中定义一个方法来满足您的需求。
type MyInt16 = MyInt16 of int
with
static member Mult(x, y) =
match x,y with
| MyInt16 x', MyInt16 y' -> MyInt16 (x' * y')
type MyInt32 = MyInt32 of int
with
static member Mult(x, y) =
match x,y with
| MyInt32 x', MyInt32 y' -> MyInt32 (x' * y')
还有一个使用通用类型约束的内联函数,使用这种看起来有些奇怪的语法
let inline mult (x:^T) (y:^T) = (^T : (static member Mult: ^T -> ^T -> ^T) (x, y))
然后进行测试
let a = MyInt16 2
let b = MyInt16 3
let c = mult a b
这个有效。看看使用不同类型会发生什么
let d = mult a (MyInt32 3)
以上会让您收到错误信息。
c) 您无法完全控制您的类型
也就是说,您不能在类型内定义方法,而必须使用扩展方法。扩展方法的问题是它们不能与使用通用类型约束的内联函数一起使用。在这种情况下,最好回退到我在此处描述的参数方法。
type MultParam =
| MyInt16Param of System.Int16
| MyInt32Param of System.Int32
with
static member op_Implicit(x: System.Int16) = MyInt16Param x
static member op_Implicit(x: System.Int32) = MyInt32Param x
然后再次定义一个带泛型约束条件的内联函数,将您的输入类型转换为包装器类型。
let inline (!>) (x:^a) : ^b = ((^a or ^b) : (static member op_Implicit : ^a -> ^b) x)
并添加您的实现。这次需要使用模式匹配,因此文字会多一些。
let inline mult' (x: ^T) (y: ^T) : ^T =
let x' = !> x
let y' = !> y
let r =
match x', y' with
| MyInt16Param x'', MyInt16Param y'' -> x'' * y'' |> box
| MyInt32Param x'', MyInt32Param y'' -> x'' * y'' |> box
| _ -> failwith "Not possible"
r :?> _
现在让我们再次进行测试
let e = mult' (int16(2)) (int16(3))
这可以运行。让我们看看当我们使用不同的类型会发生什么。
let f = mult' (int16(2)) (int32(3))
您IP地址为146.190.162.183,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。