Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Val without Self Identifier

Tags:

f#

Just curious why F# has: member val Foo = ... with get, set While omitting the self identifier (e.g. this.). This is still an instance property. Maybe I am the only one confused when using it. But just bothered me enough to query whoever knows how the language was defined.

like image 818
TalBeno Avatar asked May 08 '26 20:05

TalBeno


1 Answers

With this syntax, the property is almost totally auto-implemented -- all you provide is the initialization code, which essentially runs as part of the constructor.

One of the best-practice guard rails F# puts in place is that it does not let you access instance members before the instance is fully initialized. (wow, crazy idea, right?).

So you would have no use for a self-identifier in auto-props, anyways, since the only code you get to write is init code that can't touch instance members.

Per the MSDN docs (emphasis mine):

Automatically implemented properties are part of the initialization of a type, so they must be included before any other member definitions, just like let bindings and do bindings in a type definition. Note that the expression that initializes an automatically implemented property is only evaluated upon initialization, and not every time the property is accessed. This behavior is in contrast to the behavior of an explicitly implemented property. What this effectively means is that the code to initialize these properties is added to the constructor of a class.

Btw, if you try to be a smartass and use the class-level self-identifier to get around this, you'll still blow up at runtime:

type A() as this =
    member val X =
        this.Y + 10
        with get, set

    member this.Y = 42

let a = A()

System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
   at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.FailInit()
   at FSI_0013.A.get_Y()
   at FSI_0013.A..ctor()
   at <StartupCode$FSI_0014>.$FSI_0014.main@()

Edit: Worth noting that in upcoming C# 6, they also now allow auto-props with initializers (more F# features stolen for C#, shocker :-P), and there is a similar restriction that you can't use the self-identifier:

class A
{
    // error CS0027: Keyword 'this' is not available in the current context
    public int X { get; set; } = this.Y + 10;
    public int Y = 42;
    public A() { }
}
like image 160
latkin Avatar answered May 10 '26 14:05

latkin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!