Add WHEN construct, like switch, but better! #2989
-
A traditional switch is basically just a statement that can substitute a series of simple if/else that make basic checks. However it cannot replace all sort of if/else sequences but just those which compare a value with some constant. So, you can only use a switch to perform an action when one specific variable has a certain precise value.
|
Beta Was this translation helpful? Give feedback.
Replies: 19 comments
-
Are you aware of the C# 7.0 In other words, this is an area that has been actively worked on in the past few releases of C# and is likely going to be further improved in the next few releases to come. |
Beta Was this translation helpful? Give feedback.
-
Without more details and some examples it's a little difficult to ascertain what the poster is asking for, but it sounds kind of like VB.NET's Select Case True
Case Sky = Blue
DoSomething()
Case Water = Wet
DoSomethingElse()
Case 2 + 2 = 4
DoOtherSomething()
End Select |
Beta Was this translation helpful? Give feedback.
-
These should be all about feature gap between statements and expressions. I'd really want rust style expressions here:
Another reason for not using long |
Beta Was this translation helpful? Give feedback.
-
That's a tooling problem, not a language problem. |
Beta Was this translation helpful? Give feedback.
-
How I wish we could mix .vb and .cs in a same project. |
Beta Was this translation helpful? Give feedback.
-
Such syntax already exists in C#. It's just ugly: // Statement form:
switch (true)
{
case true when sky == Blue:
DoSomething();
break;
case true when water == Wet:
DoSomethingElse();
break;
case true when 2 + 2 == 4:
DoOtherSomething();
}
// expression form:
var x = true switch {
_ when sky == Blue => Something(),
_ when water == Wet => SomethingElse(),
_ when 2 + 2 == 4 => OtherSomething()
}; Both feel as much of a misuse of a However, the idea of |
Beta Was this translation helpful? Give feedback.
-
@DavidArno You can use |
Beta Was this translation helpful? Give feedback.
-
According to my #156 (very generic) if-else expression proposal, it will look like- var x =
if(sky == Blue) Something()
else if(water == Wet) SomethingElse()
else if(2 + 2 == 4) OtherSomething()
else throw new InvalidOperationException(); Edit: I forgot the expression must have an else/default path, even according to my proposal. |
Beta Was this translation helpful? Give feedback.
-
@gulshan that seems very similar to this:
|
Beta Was this translation helpful? Give feedback.
-
@sharwell, it's not so much "similar" as nigh on identical. I personally find those `if's way easier to read than nested ternary expressions though. So they are identical, save for one being readable 😉 It can be hard to justify adding new syntax that is just another way of doing something that is already supported. But in my view, ternary expressions aren't fit for purpose these days. C# continues to add expression-based features but those nested ternaries render such expressions unreadable all too easily. So I'd really like to see an expression-based It's possible though that it would be too hard to add such syntax without it being a breaking change, so I'm ready to resign myself to it never happening. |
Beta Was this translation helpful? Give feedback.
-
I find that odd given that these consturcts have existed for 40+ years across a multitude of languages and it's been fine from a readability perspective. Indeed, this is the scenario they were created to address. I'd posit that you're simply coming from a lack of familiarity with them, and that's leading to you to find them unreadable. |
Beta Was this translation helpful? Give feedback.
-
Personally I learnt and knew about the ternaries for several more years than the if-else expression. Still I always tried to avoid ternaries but had no such problem with if-else expressions. It's not that I cannot read through the nested ternary expressions. But it puts a cognitive load on me. When there are complex expressions nested in a ternary operator, it's very hard to parse mentally without parentheses and proper manual formatting. Which is not the case with if-else expressions. And I'm sure I'm not alone. Some examples contrasting them- sky == Blue ? Something() : water == Wet ? SomethingElse();
if(sky == Blue) Something() else if(water == Wet) SomethingElse();
x != 0.0 ? Math.Sin(x) / x : 1.0;
if(x != 0.0) Math.Sin(x) / x else 1.0;
age <= 12 ? 10 : age > 70 ? 15 : 0;
if(age <= 12) 10 else if(age > 70) 15 else 0; |
Beta Was this translation helpful? Give feedback.
-
It depends on your formatting. I usually either put the var result =
(sky == blue)
? Something()
: (water == Wet)
? SomethingElse()
: (2 + 2 == 4)
? OtherSomething()
: throw new InvalidOperationException(); or format it like an var result = (sky == blue) ? (
Something()
) : (water == wet) ? (
SomethingElse()
) : (2 + 2 == 4) ? (
OtherSomething()
) : (
throw new InvalidOperationException()
); or the combination of both: var result = (sky == blue) ? (
(water == wet)
? Something()
: SomethingElse()
) : (
throw new InvalidOperationException()
); The only cognitive load left is to remember not to put a semicolon after each expression. |
Beta Was this translation helpful? Give feedback.
-
My point was, I have to put parentheses and format the code manually to keep the ternary expression code readable. The default formatter is not helping me. |
Beta Was this translation helpful? Give feedback.
-
That's of course a possibility, @CyrusNajmabadi. However, I probably wrote my first ternary expression in C some 30 years ago. So if I still lack unfamiliarity with them after that many decades, either I have a problem with grasping simple concepts, or nested ternary expressions are inherently unreadable. I know which option my money is on 😆 |
Beta Was this translation helpful? Give feedback.
-
Given the language already contains the exact structure requested by this issue (i.e. the issue only requests to replace an operator character with a keyword in the same location) and the current supported form is more succinct than the current issue, I would lean against making a change to have a more verbose way to do the same thing. If density is a concern for readability of the ternary operator form, the full |
Beta Was this translation helpful? Give feedback.
-
I am also waiting for upcoming relational patterns in switch cases #2850 . Then if-else expression proposal can be kept aside. |
Beta Was this translation helpful? Give feedback.
-
@DavidArno @sharwell Just gonna throw it in here for your consideration. Consider this example: switch (intCode) {
case 404:
case 429:
case var _ when intCode >= 500:
throw new TransientManagedIdentityException($ "encountered transient managed identity service error with status code {intCode}");
case 400:
throw new BadRequestManagedIdentityException();
} What if we could omit the switch (intCode) {
case 404:
case 429:
case when intCode >= 500:
throw new TransientManagedIdentityException($ "encountered transient managed identity service error with status code {intCode}");
case 400:
throw new BadRequestManagedIdentityException();
} |
Beta Was this translation helpful? Give feedback.
-
following up on a bit older comment, but @DenisValeev's scenario looks like it would be nicely addressed by #2850 (see the Relational Patterns section) |
Beta Was this translation helpful? Give feedback.
Are you aware of the C# 7.0
when
clause for theswitch
statement, the C# 8.0switch
expression, and the change to allow theswitch
expression to be used as a statement, which might be included in C# 9.0 (#2632)? They don't address all your requirements, but I think they go a long way to solving many of them.In other words, this is an area that has been actively worked on in the past few releases of C# and is likely going to be further improved in the next few releases to come.