Allow singleline expressions in try-catch blocks #4676
Replies: 70 comments 5 replies
-
@lachbaer Did you ever create the two separate proposals to follow on from #220? |
Beta Was this translation helpful? Give feedback.
-
@yaakov-h No, I thought that it wouldn't be worthwhile, because I have inspected some code and couldn't see how And |
Beta Was this translation helpful? Give feedback.
-
@yaakov-h, I actually saw @lachbaer's proposal, but since it was closed and my proposal is a mere syntax sugar I thought about posting it separately having not found another one. |
Beta Was this translation helpful? Give feedback.
-
A big issue we had in #220 was if you nest them, you have ambiguous behaviour. For example:
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Of course rules that define the level of nesting could be defined, such as a But because If you only have one line that you want to public void Method()
{
int value;
try { value = ErrorproneFunction(); }
catch
{
// structured exception handling block
}
} This also emphasizes the explicit Another scenario is a one-line block-less try {
statement1;
statement2;
statementN;
}
catch (IOException ex) => throw new MyIOException(ex);
catch (NullReferenceException ex) => return; Because those are expressions a nesting cannot occur (as long as try-expressions aren't ready). |
Beta Was this translation helpful? Give feedback.
-
Is that not a good reason to avoid adding those same problems to |
Beta Was this translation helpful? Give feedback.
-
I agree but I don't see it as a problem. It's habit of the way we're predict our code. And since this habit already exists in the language and we're used to deal with it, I see no problem in having the same in other areas. Nested |
Beta Was this translation helpful? Give feedback.
-
The blocks are required because, unlike |
Beta Was this translation helpful? Give feedback.
-
So what? |
Beta Was this translation helpful? Give feedback.
-
What's it do? There's two perfectly legal answers. Update: Missing some necessary semicolons, fixed. |
Beta Was this translation helpful? Give feedback.
-
The |
Beta Was this translation helpful? Give feedback.
-
nesting
It ends the |
Beta Was this translation helpful? Give feedback.
-
So you'll need two flavors of the C# spec to deal with this possibility? Afterall, there could be any number of other nestable constructs under that first It's simply not worth it. If you want it all on one line feel free to wrap it in curly braces on that one line. |
Beta Was this translation helpful? Give feedback.
-
In a statement's place every 'statement' is allowed, so |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Maybe that's a good idea, maybe it isn't. But that decision should have been made before adding support for it with if-else statements. At this point, code (and the language as a whole) looks inconsistent when different rules have to be followed for different blocks of code. In addition, the ambiguity itself only exists in edge cases. Like I mentioned before, the fact that some potential edge cases exist is not a good reason to discard the entire idea.
Clarity of code is not measured solely by the number of characters. |
Beta Was this translation helpful? Give feedback.
-
The way that if-else statements works was carried forward from C (in fact, possibly from it's predecessor) so it's literally been around 50 years. Effectively this is grandfathered in to peoples thinking.
Yep. Totally agree with this. Which is why I don't believe this idea has any merit - the only benefit it has is to reduce the number of characters typed, with an increased cognitive load for everyone reading the code. Clarify of code is impaired by having ambiguous statement structures. Regrettably it can't happen because it would be a major breaking change, but I'd prefer to go the route chosen by Go (and other languages) where the |
Beta Was this translation helpful? Give feedback.
-
I agree, which is why it feels unintuitive when people use the same logic to try-catch statements and realize it doesn't work.
I don't agree that the only benefit is to reduce the number of characters typed. Having fewer characters is certainly a side-effect, but the main reason is that removing braces reduces the cognitive load for people reading the code. I understand you disagree with this, and people may well have divided opinions on it. But there certainly are a significant portion of people on this side of that divide. Individual teams could make this choice for themselves by setting code style preferences.
Not all forms of this syntax are ambiguous. There are many valid use-cases for this feature that work well. It can potentially be ambiguous when used in certain ways (which is also the case with many other C# features), the responsibility is on the developer to make the right choice in each situation.
That's an interesting opinion, I don't entirely disagree with it. |
Beta Was this translation helpful? Give feedback.
-
Punctuation matters. Removing it increases the cognitive load because now the reader has to understand how the compiler is going to parse those statements and whether or not the whitespace used by the author actually matches those rules. Relying on trivial whitespace is how bugs get introduced. The braces serve as punctuation and forces disambiguation for the reader. This was already clear 30 years ago, which is why C++ has never had a form of |
Beta Was this translation helpful? Give feedback.
-
If we had a time machine, perhaps someone could go back and work to make that happen 23 years ago. :)
As someone who knows the C# grammar inside and out, i can tell you it is massively inconsistent. To the point where i would practically argue that consistency is a non-goal (or very minor goal). When we design new stuff we consider this a bit, but it's not what we're optimizing for. Furthermore, for stuff that has already shipped, we're not going to change it just for the sake of consistency. There has to be serious value delivered on top of that for it to happen. I'm just not seeing it here. |
Beta Was this translation helpful? Give feedback.
-
Removing braces increases the cognitive load because the reader now has to create a new mental stack frame for each new block in the try-catch statement. If there's just a single statement, it's simpler to read because it doesn't create a new frame. The feature is sufficiently disambiguous, and clearer for the reader. But like I said before, people may well have divided opinions on this. Your opinion need not necessarily be held by every user of C#. Clarity is a subjective measure and code isn't clearer to everyone simply because it's clearer for you. There are a significant number of users who find it clearer without the braces. Individual teams could make this choice for themselves by setting code style preferences.
If only! :)
You may be right, but my opinion is that working to smooth out kinks is always a good direction to aim for, even if it takes a lower priority. I certainly don't expect that this feature should outweigh others that the community finds better value in.
That's a fair point - this feature is functionally just syntactic sugar. But consistency is not the only reason, clarity is another important one. A number of new features (like Expression Bodied Members from C# 6) fall in similar categories, but were still added. |
Beta Was this translation helpful? Give feedback.
-
This falls into the "There has to be serious value delivered" bucket. There's likely a 1000x (or more) benefit to expression bodied members versus braceless-try-statements. |
Beta Was this translation helpful? Give feedback.
-
Why do you hold this opinion? Doesn't it also just avoid two extra braces and a return statement i.e. creating a block of code? |
Beta Was this translation helpful? Give feedback.
-
Because the amount of code that uses properties (esp. very trivial ones) is massively more than the amount of code that needs to use trivial try/catches. |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi Fair point. Another example of a feature that arguably delivers less value than this one is Enhancement of interpolated verbatim strings. |
Beta Was this translation helpful? Give feedback.
-
And that issue has significantly less cost and doesn't result in complicated and hard-to-reason-about ambiguity resolution rules. |
Beta Was this translation helpful? Give feedback.
-
What if we strictly define that the try-catch block muct end with
Or we could also use |
Beta Was this translation helpful? Give feedback.
-
Is there any reason why requiring curly braces for nested try-catch statements that are not already contained in a code block wouldn't solve the ambiguity? try
{
try
action();
catch (Exception e)
Cleanup(e);
}
catch (Exception e)
Cleanup(e);
try
{
foreach(var variable in variables)
try
action(variable);
catch (Exception e)
Cleanup(e);
}
catch (Exception e)
Cleanup(e); Otherwise, any nested try inside of a nested block would not be ambiguous by the logic 'this try is linked to all immediate catches within the given code block': // Admittedly, 'try foreach' kind of reads like:
// "upon each iteration, try the given code block"
// Rather than:
// "try this foreach statement"
// which is not good for new C# users
try foreach(var variable in variables)
{
try
action(variable);
catch (Exception e)
Cleanup(e);
}
catch (Exception e)
Cleanup(e); I would wager the biggest con just from a syntax point of view is that users unfamiliar with this form of try-catch could be confused both what it is doing and why their compiler/IDE is forcing them to use curly braces when they first attempt to use it. If this took little to no effort to implement and analyze, I would be in favor of it. However, given:
it's unsurprisingly not a good idea to implement try statements (and thus catch statements, for consistency) without curly braces. |
Beta Was this translation helpful? Give feedback.
-
The syntax may be subjective, but the proposal is not. It's backwards compatible, so each developer would either benefit from the addition, or experience no change at all. This is an objective improvement. I agree that countless examples of unreadable code have been given, which would be enabled by this proposal. This is negligible when you consider that many developers would use the proposal to enhance the readability of their code. Analyzers exist to solve this problem. The precedent of nested
Applying the same principle to |
Beta Was this translation helpful? Give feedback.
-
I think single line try better be considered as a subset of try expression #2734 Suppport try expression that can set variable or return value would be a lot more useful |
Beta Was this translation helpful? Give feedback.
-
Please allow omission of curly braces for single-statement try-catch blocks. I'm sure this small syntactic sugar has been proposed before, although I couldn't find it.
Just like:
Beta Was this translation helpful? Give feedback.
All reactions