I am trying to write a constructor that suppose to call method defined in the class and assign result to the member. In C# it would be something like:
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);
}
}
But I have no idea how to do that it F#.
Example of two different ways of achieving this in 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
Two examples with drawbacks:
// 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
As self referential types were mentioned I would just like to point out that making a type self referential adds hidden overhead:
// 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 ()
Decompiled the overhead shows:
[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
[email protected] = this;
this.init@29-1 = 1;
}
[CompilerGenerated]
internal int computeValue()
{
// Extra checks added
return LanguagePrimitives.IntrinsicFunctions.CheckThis<Program.Test_SelfReferential>([email protected]).A + LanguagePrimitives.IntrinsicFunctions.CheckThis<Program.Test_SelfReferential>([email protected]).B;
}
}
The hidden overhead from self referential types in F# once caused me a performance regression (in some use-cases performance dropped by 50%).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With