是否可以在F#中定义通用扩展方法?

时间:2010-08-01 10:03:36

标签: f# extension-methods

我试图使用带有F#代码的Rhino Mocks,以下代码存在问题:

let service = MockRepository.GenerateMock<IMyService>()
service.Stub(s => s.Name).Return("Service");

这并不奇怪,因为Stub不是IMyService接口的一部分,它是Rhino Mocks定义的C#扩展方法。

Slighltly修改代码的工作原理:

let service = MockRepository.GenerateMock<IMyService>()
RhinoMocksExtensions.Stub<IMyService, string>(service, fun s -> s.Name).Return("Service");

但是,在F#中定义扩展方法会很好,但是它将是一个参数化的通用扩展方法,它将采用元组。我正在尝试varios语法,但没有任何运气。我没有找到F#目前是否支持这些信息。如果有人知道,请告诉我。

2 个答案:

答案 0 :(得分:4)

正如kvb所说,在F#2.0中是不可能的。在这种特殊情况下,我将包装Rhino.Mocks流畅的界面,使其在F#中更具惯用性,例如:

let mstub f target =
    RhinoMocksExtensions.Stub(target, Function(f))

let mreturn value (options: IMethodOptions<'a>) =
    options.Return value

let service = MockRepository.GenerateMock<IComparer>()
service |> mstub (fun s -> s.Compare(1,2)) |> mreturn 1 |> ignore

What's fluent in one language is not necessarily fluent in another.(对不起,但我觉得这很重要)

答案 1 :(得分:3)

如果我理解你的问题,答案是肯定的。 Section 8.12.1 of the spec(导入的C#扩展成员)包含以下文本:

  

制作C#定义的扩展成员   可用于环境中的F#代码   C#-authored程序集所在的位置   引用和公开声明   相应的命名空间在   影响。但是,有些局限性   申请,特别是

     
      
  • C#扩展成员“this”   参数是变量类型不是   在这里可以使用F#代码   F#的版本

  •   
  • C#扩展成员“this”   参数是数组类型不是   在这里可以使用F#代码   F#的版本

  •   

这解释了为什么C#中的某些扩展方法可以工作(例如System.Linq中的扩展方法),而您尝试使用的扩展方法则不会。

此外,原生F#扩展方法只能定义为放在实际的类型定义上。特别是,您不能在封闭的泛型类型(例如IEnumerable<string>)上定义F#扩展方法,也不能在泛型类型变量上定义扩展方法。