dotnet / dotnet/vblang

Qualified member access expression

Open
#138 1 comment 2 reactions 0 assignees View on GitHub
Proposal
Dominant language
No language data
Stars
328
Forks
71
PR merge metrics
No merged PRs in 30d

Description

In general, I don't like making new syntax that are just synonyms of existing syntax. I think in spirit #59 is another casting syntax. It tries to add some new capabilities that VB doesn't have today but its value is somewhere between "another CType" and "another DirectCast". That said, it does address a pain point I've seen with writing code in VB (and other languages)--_back tracking_. Today as you're merrily dotting into expressions and you get to an expression that requires casting you have to backtrack to the beginning of the term add a `CType(` then return to the original position to add a `, Type)` before continuing to dot. This is annoying but ok for a single case. It's pretty terrible if you need to do this more than once per expression since the syntactic overhead at the beginning of the term starts to pile up - `CType(CType(CType(expression.N.M.P, T1).Q.R, T2).S.T, T3).Foo`. It's cumbersome and the actual structure of what's happening is lost. It's situations like this that temp people to just late-bind everything.

On the flip side both C-style casting `(T)obj` and the proposed postfix `obj As T` casting have the problem that in most cases the next thing a user wants to do with a converted expression is dot into it, which necessitates parenthesizing the expression anyway `((T)obj).M` (and backtracking). A quick scan of the Roslyn codebase showed a lot of cases where the immediate parent of a `CType` expression was a member access expression, take [this line of code](https://github.com/dotnet/roslyn/blob/20b75912b87ef3531a0b37c61e94e2fbf91f1321/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseStatements.vb#L2183) for example.

``` VB.NET
Dim ifBlock =
CType(CType(CType(compilation.Members(0), TypeBlockSyntax).Members(0), MethodBlockSyntax).Statements(0), MultiLineIfBlockSyntax)
```

It's madness. So what if we added some syntactic sugar as a contraction for this very common case:

_expression_`.(`_Type_`.`_Name_`)`

translates to:

`CType(`_expression_`,` _Type_`).`_Name_

Then the above example becomes:

``` VB.NET
Dim ifBlock =
CType(compilation.Members(0).(TypeBlockSyntax.Members)(0).(MethodBlockSyntax.Statements)(0), MultiLineIfBlockSyntax)
```

or using our languages glorious permissive syntax:

``` VB.NET
Dim ifBlock As MultiLineIfBlockSyntax =
compilation.Members(0).(TypeBlockSyntax.Members)(0).(MethodBlockSyntax.Statements)(0)
```

The syntax is a little weird but does reflect what the user is trying to do, they want to access the `TypeBlockSyntax.Members` property of `Members(0)` and then the `MethodBlockSyntax.Statements` property of the first element of that collection (and capture it in a variable of type MultiLineIfBlockSyntax).

This would give the benefit of letting the user type more fluidly from left-to-right without backtracking while making the code more readable and not strictly inventing a new casting syntax.

It's just an idea and it might be a bridge too far and the syntax is a little clumsier with parentheses than I'd like but I'd be curious to see how it feels in prototype form (which should be cheap).

This same flow could mostly be implemented with an extension method `obj.DirectCast(Of T).Member` and that makes me think it's a bit superfluous to build into the language but for the fact that extension method can't be invoked on `Object`.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.