4

给定以下片段:

type Foo() =
    static member Test (act : unit -> unit) = act()
    static member Test (act : Action) = Foo.Test act.Invoke

我在最后一行出现错误,说明:无法根据此程序点之前的类型信息确定方法“测试”的唯一重载。可能需要类型注释。

不幸的是,类型注释(act.Invoke : unit -> unit)不能解决歧义,我找不到可以修复它的注释。我希望该Action版本是该版本的包装器->。我的特定用例是定义一个将从 F# 和 C# 调用的类,因此我希望它能够在两种语言中本地工作。

4

2 回答 2

4

F# 为您插入转换Action,因此您可以(理论上)使用一种方法。

type Foo() =
    static member Test (act : Action) = act.Invoke()

Foo.Test (fun () -> ())

我不知道如何强制编译器在 和 之间进行Action选择unit -> unit。另外两个选项:

  1. 使Action过载成为主要并做Foo.Test(Action(act))
  2. 将逻辑放在从公共方法调用的第三个函数中

但我的建议是采用单一方法Action。由于转换是自动的,因此互操作在某种意义上是免费的。

于 2012-04-17T20:47:11.993 回答
1

正如 Daniel 所说,您可能可以跳过第一个重载,因为当采用委托的方法应用于 F# 函数值时,F# 会自动插入委托构造函数(参见规范的第8.13.6节)。

如果您真的想定义一个与您的示例具有相同表面积的类型,您可以利用 let-bound 函数不包括类型导向转换的事实(只有方法调用才这样做):

type Foo() = 
    static let test act : unit = act()
    static member Test act = test act
    static member Test (act : System.Action) = test act.Invoke

但是,这样做并不是很有用,因为如果您尝试从类外部调用第一个重载,就像您在尝试定义第二个重载时遇到的那样,您将遇到同样的问题。

于 2012-04-18T02:21:40.853 回答