Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is (AnObject).AField = AValue a syntax error in VB.NET?

Tags:

syntax

vb.net

EDIT: Modified code sample to explicitly declare return type of function.


Consider the following minimal example:

Class AClass
    Public AField As Integer

    Public Sub New(aField As Integer)
        Me.AField = aField
    End Sub

    Public Function AMethod() As Integer
        Return AField
    End Function
End Class

Module AModule

    Sub Main()

        Dim AnObject As AClass = New AClass(12)

        Dim n As Integer = (AnObject).AField  ' This is fine

        Dim m As Integer = (AnObject).AMethod() ' This is fine

        (AnObject).AField = 8 ' BC30035 Syntax Error

        AnObject.AField = 8 ' This is fine

    End Sub

End Module

How does the syntax of VB.NET work that there's a difference between these two cases? It seems that if we're calling a method, or reading a field, the parentheses are allowed, but if we're writing a field, they're not.

I've tried looking at the Visual Basic Language Reference but I didn't see anything like a formal grammar. I've also tried googling this, although it's a bit hard to come up with a good set of search keywords.


UPDATE

So I've looked over the language grammar that Jimi linked and I'm even more confused -- in particular we have

RegularAssignmentStatement  ::=  Expression  Equals  Expression  StatementTerminator

Expression  ::= SimpleExpression  |  MemberAccessExpression  | ...

MemberAccessExpression  ::=
    [ MemberAccessBase  ] Period  IdentifierOrKeyword
        [  OpenParenthesis  Of  TypeArgumentList  CloseParenthesis  ]

MemberAccessBase  ::= Expression  | ...

SimpleExpression  ::= LiteralExpression | 
         ParenthesizedExpression  | 
         SimpleNameExpression |
         ... 

SimpleNameExpression  ::=  Identifier  [  OpenParenthesis  Of  TypeArgumentList  CloseParenthesis  ]

ParenthesizedExpression  ::=  OpenParenthesis  Expression  CloseParenthesis 

According to this grammar, this isn't a syntax error! To be specific,

  • AnObject is an Identifier, hence a SimpleNameExpression, hence a Simple Expression, hence an Expression. (I didn't include the definition of identifiers here, but according to the documentation strings of alphabetic characters definitely qualify.)
  • Consequently, (AnObject) is a ParenthesizedExpression, hence a SimpleExpression, hence an Expression, hence a MemberAccessBase.
  • AField is an Identifier.
  • Putting these two together, (AnObject).AField is a MemberAccessExpression, hence an Expression
  • 8 is a LiteralExpression, hence an Expression
  • The newline at the end of the line is a StatementTerminator
  • As a result, (AnObject).AField = 8 is a RegularAssignmentStatement, according to this grammar.

So, according to the document, this statement ought to parse!

like image 848
Daniel McLaury Avatar asked Feb 13 '26 14:02

Daniel McLaury


1 Answers

I’m purely guessing here but I’d say that this is an artefact of VB’s feature to force value over reference passing by using parentheses:

Sub ChangeMe(ByRef x As Integer)
    x += 1
End Sub

Dim x = 1
ChangeMe(x)   ' x = 2
ChangeMe((x)) ' still x = 2

In your code, the compiler probably treats (AnObject) as a value rather than a reference to the original object, determines that an assignment to a field would therefore be discarded, and disallows the assignment.

Of course even when passing AnObject to a method by value, modifying AnObject.Field would still modify the original object. So, by analogy, the code should work. I’m guessing that the VB compiler is applying a faulty heuristic here.

like image 73
Konrad Rudolph Avatar answered Feb 15 '26 05:02

Konrad Rudolph



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!