例如,如果我在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 = ...
Run Code Online (Sandbox Code Playgroud)
它在F#中运行良好open Lib,但是,如果我想在C#中使用它(我只对类型和成员函数感兴趣Lib),每次我创建一个我必须的类型new Lib.A(...).它变得相当烦人,没有办法省略模块名称.调用静态方法Lib.A.C()就更麻烦了.
然后,我尝试更换module用namespace,每个我介绍了一些辅助功能的时间我要创建一个新名称的新模块.偶尔我可以设法将所有辅助函数重新排列到1个模块中,但这会导致代码不太可读.
什么是更好的结构?
希望我拥有:Using * = Lib.*对于C#.
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 = ()
Run Code Online (Sandbox Code Playgroud)
F#系列遵循类似的设计.您可以使用[<AutoOpen>]和[<RequireQualifiedAccess>]属性进一步控制F#中模块的使用方式.
我认为您已经在答案中提到了最佳选择 -namespace在顶部使用声明定义文件(这样,您可以只using Lib用 C# 编写),然后将所有辅助函数放入模块中。
与某种类型(例如,与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
Run Code Online (Sandbox Code Playgroud)