-
Notifications
You must be signed in to change notification settings - Fork 66
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 for example.
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:
Dim ifBlock =
CType(compilation.Members(0).(TypeBlockSyntax.Members)(0).(MethodBlockSyntax.Statements)(0), MultiLineIfBlockSyntax)or using our languages glorious permissive syntax:
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.