-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Permit expression statements within the new switch expression and allow it to be an expression statement itself #1558
Comments
I don't understand what this means. Each "switch expression arm" (the term used by the compiler prototype for switch expression cases) has an expression, not a statement after the arrow. So I don't understand how are |
I am quite likely using the wrong terms. Just as an expression-bodied method can either have an expression (if it returns a value), or an |
I think I understand what you mean now. The term you're looking for is
And you're proposing the same limitation for the expressions in the arms of a switch expression, if the switch expression is treated as a statement expression. |
Thanks for the clarification re a statement expression and expression statement. I'd missed the fact that they were different things. I think it might already support those statements in the arms of the switch expression. For example, the following code only complains on the void discard (or if I try to use the switch expression as a statement): class Program
{
static void M(Shape s)
{
_ = s switch
{
Circle c when c.Radius > 10 => DoSomethingWithCircle(c),
Rectangle r when r.Width > 10 => DoSomethingWithRectangle(r),
_ => DefaultAction()
};
}
private static void DefaultAction() {}
private static void DoSomethingWithCircle(Circle circle) {}
private static void DoSomethingWithRectangle(Rectangle circle) {}
}
class Shape{}
class Circle : Shape
{
public int Radius;
}
class Rectangle : Shape
{
public int Width;
} So I think the only thing I'm actually asking for here is for a switch expression to be treated as a statement expression (or expression statement; not sure which 😄) |
I don't think that this would work terribly well without changing how expressions work in C# on a larger scale. As with the ternary conditional operator the C# compiler is going to expect that all arms collapse to a single type which will become the type of that expression. So if any of those functions or expressions invoked in an arm happen to return a value that would result in a compiler error: s switch {
Circle c when c.Radius > 10 => circles.Add(c), // Add happens to return bool
_ => Console.WriteLine("nope")
}; This is different from where you can use statement expressions today because the compiler knows that the expression would result in void: Action a = () => Console.WriteLine("foo");
void lfn() => Console.WriteLine("bar"); But the compiler won't know that here, not unless it considers how the result might be assigned. Attempting to have the compiler resolve |
This already happens with the recursive patterns branch. For example, in the code above, change private static bool DefaultAction() => true; and the only error from the compiler is So I don't think your concern is valid here. |
That the compiler would so quickly fail is my concern. It makes a large number of methods that happen to return a value but where that value is safely ignored unsuitable to be used here. This isn't an issue anywhere else that you can use a statement expression because the compiler knows to drop the return value on the floor: public void M() {
bool lfn() => true;
Action a = () => lfn(); // no problem
x switch {
V1 _ => lfn(), // problem
V2 _ => Console.WriteLine("foo")
};
} I'm not saying that this is a problem from a technical point of view, but that it's a problem from a user experience and expectation point of view. |
I disagree. The compiler error is perfectly clear: you can't mix types in the arms of the switch expression. You'd get exactly the same problem if you mixed eg a |
If you expected to assign that anywhere I would agree it doesn't make sense. I guess what I'm saying here is that if you want to treat the |
I think that what would be needed to make this work is that |
Added this as an open issue for pattern-matching. |
There are two parts to this proposal, that both hinge on my understanding of expression statements. There is a high risk that I've got it wrong...
Within the proposal, #1548, the following syntax form is used as an example in a number of cases:
Under the current plans for the switch statement, this will not compile if
DoSomethingWithCircle
,DoSomethingWithRectangle
andDefaultAction
arevoid
and/or ifDoSomething
has avoid
"return type". Many of the errors that various forms of this code give relate to a switch expression not being in the list of accepted expression statements.As I understand it, the set of statements permitted in an expression-bodied method is confined to those defined as an
expression_statement
. So there is precedence in the language for supporting such constructs. Therefore, I propose that the cases in a switch expression should themselves should supportexpression_statement
statements. I think it already does do this, but I wanted to formalise that here.Next, the switch expression itself should be added to the
expression_statement
set, which would allow it to be used as a statement, and would allow it to be used as the expression in avoid
expression-bodied method.Doing this has two advantages:
The text was updated successfully, but these errors were encountered: