I am trying to understand how the C# analyzers and compilers work.
Unary operators like pre-inc and post-inc should only accept variables, properties and indexers, according to docs.
Interestingly they also accept ParanthesisedExpressions, such as the code (x);
Is there a syntactic reason for this? Are there any other circumstances where (..something here..) works other than that the ParanthesizedExpressionSyntax is semantically equivalent to the property/indexer/variable?
CodePudding user response:
It's because the C# language specifications allow it. The specification of the preincrement operator is:
pre_increment_expression
: ' ' unary_expression
;
and the specification for the unary_expression is:
unary_expression
: primary_expression
| null_conditional_expression
| ' ' unary_expression
| '-' unary_expression
| '!' unary_expression
| '~' unary_expression
| pre_increment_expression
| pre_decrement_expression
| cast_expression
| await_expression
| unary_expression_unsafe
;
and finally, primary_expression allows for parenthesis:
primary_expression
: primary_no_array_creation_expression
| array_creation_expression
;
primary_no_array_creation_expression
: literal
| interpolated_string_expression
| simple_name
| parenthesized_expression <<--- parenthesized expression
| member_access
| invocation_expression
| element_access
| this_access
| base_access
| post_increment_expression
| post_decrement_expression
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
| typeof_expression
| checked_expression
| unchecked_expression
| default_value_expression
| nameof_expression
| anonymous_method_expression
| primary_no_array_creation_expression_unsafe
;
So now the question is: why should pre_increment_expression
allow a unary_expression
? Because the alternative would be harder to specify, to develop and then to test. The alternative would have been to write something like this:
pre_increment_expression
: ' ' pre_increment_expression_allowed
;
pre_increment_expression_allowed
: element_access
| member_access
| some other expressions
;
If you don't reuse an existing expression, you'll have to think about all the expressions you want to allow, which can become very complex, and then develop the new syntax tree parsing to support that expression.
Convoluted example:
Note that it's possible to write the following (not that it makes much sense, but still):
void Main()
{
(new MyClass().Prop);
}
public class MyClass
{
public int Prop {get;set;}
}