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.)(AnObject) is a ParenthesizedExpression, hence a SimpleExpression, hence an Expression, hence a MemberAccessBase.AField is an Identifier. (AnObject).AField is a MemberAccessExpression, hence an Expression8 is a LiteralExpression, hence an Expression(AnObject).AField = 8 is a RegularAssignmentStatement, according to this grammar.So, according to the document, this statement ought to parse!
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.
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