如何使用方法在F#

时间:2017-06-08 16:08:13

标签: f#

我正在尝试编写一个构造函数,该构造函数假设调用类中定义的方法并将结果赋给成员。在C#中,它将类似于:

public class Test
{
    public int Value { get; private set;}

    private static int SomeLogic(int a, int b)
    {
        return a + b;
    }

    public Test(int a, int b)
    {
        this.Value = SomeLogic(a,b);
    }
}

但我不知道怎么做F#。

3 个答案:

答案 0 :(得分:4)

在F#中实现此目的的两种不同方法示例:

type Test_UsesVal =
  val value : int
  new (a, b) = { value = someLogic a b }
  member x.Value = x.value

type Test_Preferred (a : int, b: int) =
  let value = someLogic a b
  member x.Value = value

两个有缺点的例子:

// This type is default constructible and when using default ctor someLogic is not used
type Test_DefaultConstructible () =
  let mutable value = 0
  new (a, b) as x = Test_DefaultConstructible () then x.Value <- someLogic a b
  member x.Value with get () = value and private set v = value <- v

// This type has 2 constructors and using single value ctor someLogic is not used
type Test_2Constructors (value : int) =
  new (a, b) = Test_2Constructors (someLogic a b)
  member x.Value with get () = value

由于提到了自引用类型,我只想指出一个类型自引用会增加隐藏的开销:

// Self referential types add hidden overhead
type Test_SelfReferential (a : int, b: int) as this =
  let computeValue () = someLogic this.A this.B

  member x.A      = a
  member x.B      = b
  member x.Value  = computeValue ()

对开销节目进行了反编译:

[CompilationMapping(SourceConstructFlags.ObjectType)]
[Serializable]
public class Test_SelfReferential
{
  internal int b;

  internal int a;

  // An extra field added
  internal FSharpRef<Program.Test_SelfReferential> @this = new FSharpRef<Program.Test_SelfReferential>(null);

  // An extra field added
  internal int init@29-1;

  public int A
  {
    get
    {
      // An extra check added in each method 
      if (this.init@29-1 < 1)
      {
        LanguagePrimitives.IntrinsicFunctions.FailInit();
      }
      return this.a;
    }
  }

  public int B
  {
    get
    {
      // An extra check added in each method 
      if (this.init@29-1 < 1)
      {
        LanguagePrimitives.IntrinsicFunctions.FailInit();
      }
      return this.b;
    }
  }

  public int Value
  {
    get
    {
      // An extra check added in each method 
      if (this.init@29-1 < 1)
      {
        LanguagePrimitives.IntrinsicFunctions.FailInit();
      }
      return this.computeValue();
    }
  }

  public Test_SelfReferential(int a, int b) : this()
  {
    this.a = a;
    this.b = b;
    // An extra init added in .ctor
    this.@this.contents = this;
    this.init@29-1 = 1;
  }

  [CompilerGenerated]
  internal int computeValue()
  {
    // Extra checks added
    return LanguagePrimitives.IntrinsicFunctions.CheckThis<Program.Test_SelfReferential>(this.@this.contents).A + LanguagePrimitives.IntrinsicFunctions.CheckThis<Program.Test_SelfReferential>(this.@this.contents).B;
  }
}

F#中自引用类型的隐藏开销一度导致我的性能回归(在某些用例中性能下降了50%)。

答案 1 :(得分:3)

.swiper-button-next {
visibility:        none;
}

.swiper-button-prev
{
visibility:        none;
}

请注意,单个param构造函数是私有的。因此,让a = Test(1)是不可能的。

也许不需要setter或mutable字段。如果是的话......

type Test private (constructorParam) =

    let mutable value = constructorParam

    member this.Value
      with get()                = value 
       and private set newValue = value <- newValue

    static member SomeLogic(a,b) = a+b

    new(a,b) = Test(Test.SomeLogic(a,b))

let a = Test(1,2)

的引用:

答案 2 :(得分:1)

您可以在构造函数的开头使用as绑定:

type SomeClass() as this =

    do printfn this.Member1

    member this.Member1 = "s"

您可以随意调用它:x等,但我认为只使用this就行了。

您可以在此处详细了解自我标识符https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/classes

编辑:如果需要初始化该类型的任何私有字段,可以在构造函数中定义函数,在初始化中使用它,然后将其公开为公共成员:

let func x = ...
let field = func 0
member this.Method(x) = func x