如何向C#和F#公开尽可能友好的类型?

时间:2013-01-22 16:44:05

标签: f#

例如,如果我在F#中编写了一个模块

module Lib

type A =
    member this.x1 x = ...

let helpa x = ...
let helpb x = ...

type B =
    member this.y1 x = ...

let helpc x = ...

typeA with
    member this.x2 x = ...
typeB with
    member this.y2 x = ...

它在open Lib的F#中运行良好,但是,如果我想在C#中使用它(我只对Lib中的类型和成员函数感兴趣),每次我创建一个类型我必须new Lib.A(...)。它变得相当烦人,没有办法省略模块名称。调用像Lib.A.C()这样的静态方法更加麻烦。

然后我尝试用module替换namespace,每次我介绍一些辅助函数时,我必须创建一个带有新名称的新模块。偶尔我可以设法将所有辅助函数重新排列到1个模块中,但这会导致代码不太可读。

这会是一个更好的结构吗?

希望我有:Using * = Lib.*代表C#。

2 个答案:

答案 0 :(得分:7)

F#提供了比C#更多的灵活性,所以我会以标准方式将它暴露给C#,即将类型包含在命名空间中。我认为,这样的事情提供了两全其美的优势:

namespace Lib

type A =
    member this.x1 x = ()

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module A =
  let helpa x = ()
  let helpb x = ()

type B =
    member this.y1 x = ()

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module B =
  let helpb x = ()

type A with
    member this.x2 x = ()
type B with
    member this.y2 x = ()

F#系列遵循类似的设计。您可以使用[<AutoOpen>][<RequireQualifiedAccess>]属性进一步控制F#中模块的使用方式。

答案 1 :(得分:4)

我认为你已经在你的答案中提到了最好的选项 - 在顶部用namespace声明定义文件(这样,你可以在C#中只编写using Lib)然后放置所有辅助函数在模块中。

与某种类型明确关联的辅助函数(例如,使用A)可以放入名为A的模块中(类似于List模块中与之关联的F#函数List<'T>类型)。

这是一项更多的工作,因为你需要使用特殊属性标记模块(以避免名称冲突),但它很容易从F#和C#中使用(我认为好用的更重要而不是在构建库时保存几个键击:)

namespace Lib

// Declaration of the 'A' type and helper functions in 'A' module 
type A() =
  member this.x1 x = 10

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module A = 
  let helpa (x:A) = x.x1
  let helpb (x:A) = x.x1

// Declaration of the 'B' type and helper functions in 'B' module 
type B() =
  member this.y1 x = 10

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module B = 
  let helpc (x:B) = x.y1

// Member augmentations for easy use from C#
type A with
    member this.x2 x = A.helpa this
type B with
    member this.y2 x = B.helpc this