Recap
Current syntax (from lang ref):
UserDefinedAttribute:
@ ( TemplateArgumentList )
@ TemplateSingleArgument
@ Identifier ( NamedArgumentList[opt] )
@ TemplateInstance
@ TemplateInstance ( NamedArgumentList[opt] )
TemplateSingleArgument:
Identifier
FundamentalType
CharacterLiteral
StringLiteral
InterpolationExpressionSequence
IntegerLiteral
FloatLiteral
true
false
null
this
SpecialKeyword
After expanding TemplateSingleArgument
, we have this:
UserDefinedAttribute:
@ ( TemplateArgumentList )
@ CharacterLiteral
@ StringLiteral
@ InterpolationExpressionSequence
@ IntegerLiteral
@ FloatLiteral
@ true
@ false
@ null
@ this
@ SpecialKeyword
@ FundamentalType
@ Identifier
@ Identifier ( NamedArgumentList[opt] )
@ TemplateInstance
@ TemplateInstance ( NamedArgumentList[opt] )
Proposal #1
Replace comma-separated list of expressions
@ ( TemplateArgumentList )
with single expression
@ ( TemplateArgument )
Example: instead of @(A,B,C)
, one should write @(A) @(B) @(C)
.
I believe this is much clearer because it forces single attribute per single @
-expression. This will also reduce cognitive load on weird things like @(_=>(2,4),2,4,_=>2,4)
.
Proposal #2
Replace
@ FundamentalType
@ Identifier
@ Identifier ( NamedArgumentList[opt] )
@ TemplateInstance
@ TemplateInstance ( NamedArgumentList[opt] )
with parts of PostfixExpression and PrimaryExpression:
UserDefinedAttribute:
...
@ UserDefinedAttributeExpression
UserDefinedAttributeExpression:
FundamentalType
Identifier
. Identifier
TemplateInstance
. TemplateInstance
UserDefinedAttributeExpression . Identifier
UserDefinedAttributeExpression . TemplateInstance
UserDefinedAttributeExpression ( NamedArgumentList[opt] )
This will allow writing !
/.
-chained expressions without parentheses:
@A!B.C(D)
instead of @(A!B.C(D))
currently.
Proposal #3
Remove undocumented behavior from compiler which allows using lambda in UDA without parentheses:
@_ => 2
int a;
In this case, one should be forced to use parentheses:
@(_ => 2)
int a;