Rule to format ternary expression

Apr 12, 2011 at 9:54 PM

Hi,

I'd like to propose new readability rule for ternary expressions. Valid options should be:

a) whole expression in one line:

int x = booleanExpression ? firstIntValueExpression : secondIntValueExpression;

b) each expression on its own line, with "?" and ":" as starting characters:

int x = booleanExpression
    ? firstIntValueExpression
    : secondIntValueExpression;

Rationale for placement expressions in separate lines: consistency with parameters and statement rules - parameters should be in one line or each in separate lines, statements should be each in its own line. Also having each expression in its own line allows to easy grasp where each expression starts and ends.

Rationale for "?" and ":" placement: when these operators are placed at the beginning of line, one can easy see that rest of the line is part of ternary expression. When these operators are placed at the end of line and expressions are long, "?" and ":" can go out of view. This makes harder to see that ternary expression is used.

Coordinator
Apr 15, 2011 at 10:06 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Developer
Apr 16, 2011 at 3:26 PM

In my opinion, such rule should be implemented in tandem with another rule that checks operator position.

I'm talking about 2 different styles:

#1 "Operators at the beginning"

if (a > 1
    || b > 2
    || c > 3)
...

int x = (1 + 23)
    * (45 - 678)
    / (9 + 10);
...

 #2 "Operators at the end"

if (a > 1 ||
    b > 2 ||
    c > 3)
...

int x = (1 + 23) *
    (45 - 678) /
    (9 + 10);
...

The problem is that StyleCop ships "with a single, consistent set of rules, with minimal rule configuration allowed".

If we continue to follow this point, we should decide first which style has to be accepted by StyleCop - #1 or #2.
After this decision, we could implemented rules for formatting operators, ternary expressions (and maybe something else...).

Another scenario is to make an ability to choose the desired style (e.g. via settings), but it doesn't follow StyleCop "motto" and will create a precedent - many existing StyleCop rules follows only one fixed style with no ability to change it. This would make StyleCop more complex and non-transparent.

What do you think?

Best regards,
Oleg Shuruev

Coordinator
Apr 16, 2011 at 4:30 PM

I wasn't considering this for all expressions just ternary expressions.

For tenary I like:

int x = booleanExpression
    ? firstIntValueExpression
    : secondIntValueExpression;

In your other case I prefer 'operators at the end'
Developer
Apr 16, 2011 at 5:27 PM
Edited Apr 16, 2011 at 5:28 PM

Sounds reasonable. I really didn't mean that they have to be the same rule.

Personally, I use the proposed format for ternaries and "operators at the beginning" for expressions.
And the reason of placing operators at the beginning is the same is why I put ? or : at the beginning.

But if to discuss where to place operators, I'm just wondering if there are any explanations why to place operators at the end?

Best regards,
Oleg Shuruev

Apr 17, 2011 at 5:41 AM

+1

int x = booleanExpression
	? firstIntValueExpression
	: secondIntValueExpression;

As for Oleg's additional argument, I prefer form #1 - operators first.

Here's another example where I find the operator-first format to be more readable, although StyleCop currently warns about it when used as a parameter.

Regex.Matches(
	response,
	@"\< (?<Tag> \w+? ) \s [^\>]*? id= (?<Q> [""'] ) (?<ID> .+? ) \k<Q> .*? \>",
	  RegexOptions.IgnoreCase
	| RegexOptions.ExplicitCapture
	| RegexOptions.IgnorePatternWhitespace
	| RegexOptions.Singleline)
Apr 18, 2011 at 8:33 AM
Edited Apr 18, 2011 at 8:49 AM

I also prefer "operators first" approach:

  • I don't need to scan the rest of line to see what is happening
  • It allows me to edit code (delete, comment out, copy etc) as a single line operation. As such it is simpler and less error prone - I don't need to remember about operator at the end of previous line
  • It resembles my way of thinking:
    • "something" "and something else" rather than "something and" "something else"
    • "something" "plus something else" rather than "something plus" "something else", you get the idea
  • I was thought in school that substraction is just shorthand for adding a negative number. That's why for me "-" operator "belongs" to subtrahend and I like to keep them together.
  • It has also some nice default formatting when used as bool return statement. This is of course a side effect: 4 spaces of indent + 2 chars of operator and each bool part of expression starts in the same column.
    return firstBool
        && secondBool
        && thirdBool;
    

I use this only with boolean return values to leverage fact, that not all parts of expression are evaluated once we get false (for &&) or true (for ||). With arithmetic I tend to accumulate value in result variable.

But if you really want to extend this rule for other operators, maybe look at Framework source and see what MS devs prefer, #1 or #2, and select that route.