在F#中定义静态类

Gre*_*Ros 23 .net f# static

是否可以在F#中定义包含可重载成员的静态类?let模块绑定不能重载,即使它们被编译为静态类中的静态静态成员.

type declerations可以包含静态成员,但我不知道类型本身是否可以是静态的.

我目前的解决方案是type使用私有构造函数定义一个并使用它.我想知道是否有一种方法可以根据需要定义静态类型.

Joe*_*ler 36

正如Robert Jeppeson指出的那样,C#中的"静态类"只是创建一个无法实例化或继承的类,并且只有静态成员.以下是您在F#中完全实现的方法:

[<AbstractClass; Sealed>]
type MyStaticClass private () =
    static member SomeStaticMethod(a, b, c) =
       (a + b + c)

    static member SomeStaticMethod(a, b, c, d) =
       (a + b + c + d)
Run Code Online (Sandbox Code Playgroud)

这可能有点过分,因为AbstractClass私有构造函数都会阻止你创建类的实例,但是,这就是C#静态类所做的 - 它们被编译为带有私有构造函数的抽象类.该Sealed属性阻止您继承此类.

如果您像在C#中那样添加实例方法,这种技术不会导致编译器错误,但从调用者的角度来看,没有区别.


pad*_*pad 6

F# 中没有定义静态类型的工具。

第一种选择是定义一个模块,但它缺乏重载函数的能力(这就是您所追求的)。第二种选择是声明具有静态成员的普通类型。

关于第二种方法,这正是您的老问题所接受的答案所描述的。我重构了代码以使其更容易解释。首先,定义一个虚拟的单例判别联合:

type Overloads = Overloads
Run Code Online (Sandbox Code Playgroud)

其次,您利用静态成员可以重载的事实:

type Overloads with
    static member ($) (Overloads, m1: #IMeasurable) = fun (m2: #IMeasurable) -> m1.Measure + m2.Measure 
    static member ($) (Overloads, m1: int) = fun (m2: #IMeasurable) -> m1 + m2.Measure
Run Code Online (Sandbox Code Playgroud)

inline第三,使用关键字将这些重载方法的约束传播到 let-bounds :

let inline ( |+| ) m1 m2 = (Overloads $ m1) m2
Run Code Online (Sandbox Code Playgroud)

当您能够使用此方法重载 let-bounds 时,您应该创建一个包装器模块来保存这些函数并标记您的类型private


Rob*_*sen 5

我不确定是否有静态类之类的东西。我相信,C# 类级别上的“静态”是在 2.0 中引入的,主要是为了方便(避免私有构造函数和编译时检查不存在实例成员)。您无法检查类型并得出它是静态的结论:http : //msdn.microsoft.com/en-us/library/system.reflection.typeinfo.aspx

更新:MSDN 声明静态类是一个密封类并且只有静态成员:http : //msdn.microsoft.com/en-us/library/79b3xss3(v=vs.80).aspx

所以,你现在正在做的就是做这件事的方法。


Ben*_*erg 5

《 F#组件设计指南》对此进行了解释。

[<AbstractClass; Sealed>]
type Demo =
    static member World = "World"
    static member Hello() = Demo.Hello(Demo.World)
    static member Hello(name: string) = sprintf "Hello %s!" name

let s1 = Demo.Hello()
let s2 = Demo.Hello("F#")
Run Code Online (Sandbox Code Playgroud)

仍然可以定义实例方法,但是当没有构造函数可用时,您无法实例化该类。

  • 从VS2019开始,包括私有构造函数实际上会发出一个构造函数,这大概是不可用的。因此,这个答案是所希望的:它生成一个密封的静态类,当反编译时,它看起来像这样(C#):`public static class Demo {...`。省略AbstractClass会导致它不是静态类。如果您正在与另一种语言互操作,这可能会更加明显。 (2认同)