Roslyn: [Yet another] Try...catch - proposal: Drop "{" and "}" in one-liners

Created on 24 Dec 2016  路  7Comments  路  Source: dotnet/roslyn

I know that we had a lot of try...catch-proposals during the last weeks, but here is the only proposal I have to make about this subject:

Please allow to omit the brackets { and } in try/catch/finally-blocks, if the block contains a single expression:

    method();
catch (Exception ex) when (condition(ex))
    handler1(ex);
catch
    handler2();
finally
    handler3();

I personally find it irksome, if one has to type { and } explicitly for simple expressions as in the example above.
Allowing this new syntax would also be consistent with any other 'block-type expression' (dunno what they are officially called) like if, else, for, foreach, do, while, fixed, using, etc.
I also believe that this proposal should not take a very huge effort/workload to implement, as we have such analyzation methods already implemented in the syntax parser.

related: https://github.com/dotnet/roslyn/issues/16072#issuecomment-269029360


_And of course, merry Christmas to everyone!!_

Area-Language Design Discussion

Most helpful comment

This will be ambigious in case of nested try-catch statements, for example:

try
    M();
catch(ExceptionA)
    try
        M();
    catch(ExceptionB)
        M();
catch
    M();

could be interpreted as:

try { M(); }
catch(ExceptionA)
{
  try { M(); }
  catch(ExceptionB) { M(); }
}
catch { M(); }

or:

try { M(); }
catch(ExceptionA)
{
  try { M(); }
  catch(ExceptionB) { M(); }
  catch { M(); }
}

This is known as "dangling else ambiguity" for if-else statements, but since you have a single else per if statement the compiler can associate it to the lexically nearest preceding if.

All 7 comments

This will be ambigious in case of nested try-catch statements, for example:

try
    M();
catch(ExceptionA)
    try
        M();
    catch(ExceptionB)
        M();
catch
    M();

could be interpreted as:

try { M(); }
catch(ExceptionA)
{
  try { M(); }
  catch(ExceptionB) { M(); }
}
catch { M(); }

or:

try { M(); }
catch(ExceptionA)
{
  try { M(); }
  catch(ExceptionB) { M(); }
  catch { M(); }
}

This is known as "dangling else ambiguity" for if-else statements, but since you have a single else per if statement the compiler can associate it to the lexically nearest preceding if.

@alrz Is this what you're referring to? Due to indentation the intent was that NotA() runs if !a, but in fact it doesn't because it's associated to the nearer if?

c# if (a) if (b) AAndB(); else NotA();

You could apply the same logic to the dangling catch blocks, right? Associate them all to the lexically nearest preceding try?

An alternative might be to disallow a try statement as a single nested statement inside either a try, catch or finally block. That would enforce better readability, but would break with the if precedent. I kinda prefer it nonetheless.

Proposal: Try ... Else Try #16078

@jnm2 In my opinion, allowing it in certain circumstances other than introducing unnecessary complexity into the parser, would be confusing because it wouldn't be clear that what was the developer intention vs. how the compiler would behave. It is in fact consistent with itself rather than semi-consistent with other constructs. It probably wouldn't be technically ambigious to allow it, but it can mean different things which is just not acceptable. Using braces is often considered best practice as you can see in the Roslyn codebase itself. My guess is that try-catch is not seen as a "lightweight" construct in the same sense asif, so perhaps conciseness won't necessarily bring better readability in that context.

@alrz : Concerning your point about nested try-catches: that is a good point, which I have not thought about ...... maybe one should do as @jnm2 has proposed:

An alternative might be to disallow a try statement as a single nested statement inside either a try, catch or finally block.

I'm one of these devs that use braces everywhere, I actually think that they add clarity to the code, especially in nested blocks, I do that for single if statements too because I'm fanatic, pedantic or both, I'll let you decide... 馃槅

However, I know it's a style thing but how common it is to have a single call per block? and even more so how common it is to do exception handling? it's more common to throw exceptions than dealing with them, not to mention that people that write applications deal with exceptions sparingly.

Now, don't get me wrong, I do think that there's certainly a place for improvements and exception handling can be a lot terser but in my opinion it needs to be more useful than losing the braces and again the reason is we're not doing exception handling on every method call or anything close to _often_.

Just my 2c. :)

This discussion has moved to https://github.com/dotnet/csharplang/issues/616 and this issue should be closed.

Was this page helpful?
0 / 5 - 0 ratings