在运行时v.s.分配无成员类型在编译时绑定

时间:2013-09-19 18:21:00

标签: performance f#

这是两个F#场景。我有一个抽象类:

type IAbstractObj =
    abstract DoSomething : bool -> bool

场景1:

我将接口实现为一个类型:

type ConcreteObj = 
    interface IAbstractObj with
        member this.DoSomething bool = true

然后通过实例化在应用程序中使用它:

let foo = new ConcreteObj();

场景2:

我使用let绑定绑定了该类型的实例,并将其用作“自由函数持有者”:

let ConcreteObj = {
    new IAbstractObj with
        member this.DoSomething bool = true
}

并按原样使用:

let foo = ConcreteObj

这些用法有何不同?在任何一种情况下,类型都不需要保留任何额外的运行时状态。

  • 会有性能差异(微不足道)吗?对于包含'let'绑定的模块,内存是否仅分配给在应用程序的其他部分中实际评估的绑定?
  • 方案1是否会分配少量内存来保存指向实例的指针(即使它是无状态的)?

这对我的应用来说非常重要。我使用许多接口用于验证器和序列化器,它们不包含任何实例状态。有了我的C#背景,我习惯于拥有来创建一个继承接口的类的实例,即使它有一个无参数的构造函数,显然只是一个基本静态函数的持有者。 p>

2 个答案:

答案 0 :(得分:3)

两者之间的主要区别在于对象表达式具有它实现的接口或抽象类的静态类型。然而,基于类的接口实现是显式的,并且需要强制转换才能访问接口成员。

对于简单的接口实现,对象表达式通常是比类更好的选择。

(FWIW,我认为您的性能问题无关紧要。)

答案 1 :(得分:3)

有一个比其中任何一个更惯用的选项。不要为每个选项创建新类型,只需创建一个记录类型,其中有两个成员即函数。你几乎在评论中自己定义了它:

type serializer<'a, 'b> = 
    { Serialize : 'a -> 'a Option
      Deserialize: 'b -> 'b Option}

let concrete = { Serialize = (fun (x)->Some(x)); Deserialize = (fun (x)->Some(x)) }

因此无论消费多少都需要serializer