例如,如果我在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#。
答案 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