2010-08-01 31 views
5

我試圖用犀牛製品與F#代碼,下面的代碼是有問題的:是否可以在F#中定義一個通用的擴展方法?

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

這並不奇怪,因爲存根不IMyService接口的一部分,這是一個C#擴展方法是犀牛製品定義。

Slighltly修改代碼的工作:

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

然而,這將是很好的定義在F#的擴展方法,但那麼這將是這將需要一個元組參數化通用的擴展方法。我正在嘗試varios語法,但沒有任何運氣。我沒有找到信息,目前是否支持F#。如果有人知道,請告訴我。

回答

3

如果我正確理解你的問題,答案是否定的。 Section 8.12.1 of the spec(進口C#擴展成員)包括這樣的文字:

C#-defined延伸構件在環境 其中C#-authored組件是 引用和 相應的命名空間的開放聲明做出 提供給F#代碼在 的影響。然而,一些限制 應用,特別是

  • C#擴展成員,其「本」 參數是一個變量的類型在這個 版本F#的不 提供給F#代碼

  • C#延長元件其「這」 參數是在該 版本F#的陣列型不 提供給F#代碼

這解釋了爲什麼C#中的一些擴展方法可以工作(例如,那些在System.Linq),而你正在嘗試使用的不會。

此外,本機F#擴展方法只能定義爲放置在實際類型定義上。尤其是,您不能在封閉泛型類型上定義F#擴展方法(例如IEnumerable<string>),也不能在泛型類型變量上定義擴展方法。

+0

謝謝你答案! – 2010-08-02 08:29:38

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.(遺憾的插頭,但我真的認爲這是與此有關)

+0

Marurcio, 謝謝你的解釋。是的,我也得出了相同的結論,即這種在C#中非常有用的擴展不會爲F#帶來太多價值,並且在F#中有其他(和更好的)表達方式。 – 2010-08-02 08:32:13

相關問題