Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static Property Variables #195

Closed
AnthonyDGreen opened this issue Nov 1, 2017 · 5 comments
Closed

Static Property Variables #195

AnthonyDGreen opened this issue Nov 1, 2017 · 5 comments

Comments

@AnthonyDGreen
Copy link
Contributor

Some set of people have asked us to enable fields scoped to a property. VB already has Static local variables, which as effectively fields scoped to their containing method. For lazily computed read-only variables this already enables one to write code where the backing store of a ReadOnly property is entirely local to that property. We could extend this to come up with a syntax for property scoped fields:

Property P As T
    Static F As T
    Get
        Return F
    End Get
    Set(value As T)
        F = value
    End Set
End Property

This works around a syntactic ambiguity with Dim since Dim could also be the start of a field declaration:

Property P As T
' Parser decided this was an auto-prop because next statement wasn't a Get or Set.
Dim F As T

' Parser starts to flip out right about here.
    Get
        Return F
    End Get
    Set(value As T)
        F = value
    End Set
End Property

We could still work around this without the special syntax with "statement" look-ahead, whereby the parser keeps accumulating field declarations until it hits either an accessor or something which can't be in a property. If it hits a property accessor it consumes all the field statements as its children. If it hits something else if closes itself and leaves all those field declarations "around" for the class to pick up as its children. This sounds a little messy but it's actually an extremely unlikely scenario to happen in practice. If, however, we elected to allow other modifiers like Private the scenario becomes more common, though still solvable. Either way, the multi-statement "look-ahead" isn't wasteful since those statements were going to be parsed as fields anyway. We don't need to throw away any work and re-parse.

@rskar-git
Copy link

I like "Implicit property backing fields #196" very much. This "Static Property Variables #195" however is so meh. I don't see a need for #195, and it looks to be the start of some bad habits.

Ye olde Static made a little bit of sense in the primative days of BASIC - in a way it allowed a Sub or Function to seem object-ish and have a state. Essentially it mimics a singleton with exactly one method and whatever number of private fields.

But now we have classes etc. Not sure how Static fits into this style as something essential. Maybe it's to be avoided in new code?

Finally, giving a Property its own set of private fields seems like an antipattern - can you imagine the fun of troubleshooting something like that, where Static's are less observable (via the IDE) than the Private members of a project?

@reduckted
Copy link
Contributor

I'm not sure that Static is a good choice of modifier. Static locals end up with thread-safe initialization, and I'd say that in 99.9% of cases, that thread-safety is unnecessary.

Just as an example, this code:

Public Class Foo
    Public Sub Bar()
        Static meep As Integer = 1
        meep = meep + 1
    End Sub
End Class

results in the following compiled code:

Public Class Foo
    Private $STATIC$Bar$2001$meep As Integer

    Private $STATIC$Bar$2001$meep$Init As StaticLocalInitFlag

    Public Sub Bar()
        If Me.$STATIC$Bar$2001$meep$Init Is Nothing Then
            Interlocked.CompareExchange(Of StaticLocalInitFlag)(Me.$STATIC$Bar$2001$meep$Init, New StaticLocalInitFlag(), Nothing)
        End If
        Dim flag As Boolean = False
        Try
            Monitor.Enter(Me.$STATIC$Bar$2001$meep$Init, flag)
            If Me.$STATIC$Bar$2001$meep$Init.State = 0S Then
                Me.$STATIC$Bar$2001$meep$Init.State = 2S
                Me.$STATIC$Bar$2001$meep = 1
            ElseIf Me.$STATIC$Bar$2001$meep$Init.State = 2S Then
                Throw New IncompleteInitialization()
            End If
        Finally
            Me.$STATIC$Bar$2001$meep$Init.State = 1S
            If flag Then
                Monitor.[Exit](Me.$STATIC$Bar$2001$meep$Init)
            End If
        End Try
        Me.$STATIC$Bar$2001$meep += 1
    End Sub
End Class

If all that people are asking for is "fields scoped to a property", then all of the extra thread-safety seems unnecessary. So either you end up with this extra overhead because you have to use Static, or a Static local in a property behaves differently to a Static local in a method.

I'm not sure how practical this is, but what about another "accessor" in a property declaration where you can define the variables that are scoped to the getter and setter.

Property P As T
    Variables
        Dim myVariable As T = 1
        Static myStatic As T = 2
        Const myConst As T = 3
    End Variables
    Get
        Return myVariable
    End Get
    Set(value As T)
        myVariable = value
    End Set
End Property

It would give you the full flexibility of using Dim, Static or Const as desired, without resulting in ambiguity while parsing.

@rskar-git
Copy link

Before we go down this rabbit-hole, can someone explain why this "work-around" is so onerous?:

Dim _P As T         ' <== #196 removes the need for this
Property P As T
    Get
        Return _P
    End Get
    Set(value As T)
        _P = value
    End Set
End Property

Or, what real advantage does #195 provide?

@Bill-McC
Copy link

Bill-McC commented Nov 4, 2017

I think the advantage is it would "pretend" to only allow the field to be modified inside the property, thus ensuring any event wiring isn't bypassed etc. Reflection, where allowed, would bypass this as a field is still a field.

The other advantage is code organisation/ refactoring. If you delete the property P you have to still delete the field and vice versa. Having them next to each other makes that a bit easier but also messes up appearance of collapsed code.

I like the idea, but would like the syntax to be exactly the same as if the field was declared outside the Property. Not "Static", but "Private" "Public", "Friend" and "Dim". I should be able to edit the code by simple drag and drop of fields into their property declaration or out. And if a field is Private or Dim, then if it is accessed outside the property I'd expect a compiler warning.

@AnthonyDGreen
Copy link
Contributor Author

AnthonyDGreen commented Dec 7, 2017

Update: The 11/15/2017 LDM rejected this idea. In short, we didn't think it was worth special-casing fields. The existing scenario seems adequately addressed with fields not being private to a property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants