Skip to content
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: allow comparison operators in switch case labels C# #11312

Closed
JFMous opened this issue May 14, 2016 · 6 comments
Closed

Proposal: allow comparison operators in switch case labels C# #11312

JFMous opened this issue May 14, 2016 · 6 comments

Comments

@JFMous
Copy link

JFMous commented May 14, 2016

It would be nice if the case labels in switch statement supported comparison operators, much like the Select Case statement in Visual Basic does.

Now, there are only two options for the switch labels:

switch-label:
case constant-expression :
default :

This could be extended to:

case [< | > | <= | >=] constant-expression [ to ] constant-expression :
default :

So you could write code as in this example:

int iq = DoIqTest();

switch (iq)
{
    case <= 69:
        ProcedureExtremelyLow();
        break;
    case 70 to 79:
        BorderlineProcedure();
        break;
    case 80 to 89:
        LowAverageProcedure();
        break;
    case 90 to 99:
    case 101 to 109:
        AverageProcedure();
        break;
    case 100:
        ExactlyMedianProcedure();
        break;
    case 110 to 119:
        HighAverageProcedure();
        break;
    case 120 to 129:
         SuperiorProcedure();
         break;
    case >= 130:
        VerySuperiorProcedure();
        break;
}

The 'to' keyword would be used to specify a range. In the statement switch (value), case x to y: would be equivalent to the boolean expression value >= x && value <= y

@HaloFour
Copy link

Case guards in pattern matching #206 will open this up to allowing for arbitrary conditions:

int iq = DoIqTest();

switch (iq)
{
    case * when iq <= 69:
        ProcedureExtremelyLow();
        break;
    case * when iq <= 79:
        BorderlineProcedure();
        break;
    case * when iq <= 89
        LowAverageProcedure();
        break;
    case * when iq == 100:
        ExactlyMedianProcedure();
        break;
    case * when iq <= 109:
        AverageProcedure();
        break;
    case * when iq <= 119:
        HighAverageProcedure();
        break;
    case * when iq <= 129:
         SuperiorProcedure();
         break;
    default:
        VerySuperiorProcedure();
        break;
}

The wildcard pattern would match on anything but then the case guard would contain the specific conditions. They would be evaluated in lexical order.

@alrz
Copy link
Contributor

alrz commented May 15, 2016

would it make sense to make case optional or perhaps switch expression?

switch {
  when id <= 69: ... break;
  ...
}

might be preferrable over if else.

@bondsbw
Copy link

bondsbw commented May 17, 2016

@alrz I like that somewhat, feels like a reasonable simplification.

But I feel this may be even more useful in pattern matching. In match expressions, the roughly equivalent form might be:

var x = match
{
    when iq <= 69: ProcedureExtremelyLow(),
    when iq <= 79: BorderlineProcedure(),
    when iq <= 89: LowAverageProcedure(),
    when iq <= 99 || (iq <= 109 && iq >= 101): AverageProcedure(),
    when iq == 100: ExactlyMedianProcedure(),
    when iq <= 119: HighAverageProcedure(),
    when iq <= 129: SuperiorProcedure(),
    default: VerySuperiorProcedure()
};

I like the possibilities but if iq is always the comparison, it really feels like it should be the subject of the match expression. Something like the following feels more like pattern matching (although it would require a bit of rethinking what a relational expression is):

var x = iq match
{
    when <= 69: ProcedureExtremelyLow(),
    when <= 79: BorderlineProcedure(),
    when <= 89: LowAverageProcedure(),
    when == 100: ExactlyMedianProcedure(),
    when <= 109: AverageProcedure(),
    when <= 119: HighAverageProcedure(),
    when <= 129: SuperiorProcedure(),
    default: VerySuperiorProcedure()
};

And I'm not sure I like changing

when iq <= 99 || (iq <= 109 && iq >= 101):

into something like

when <= 99 || (<= 109 && >= 101):

@Unknown6656
Copy link

@bondsbw, @JFMous : I would like to see something like the following implemented with the match-pattern:

Func<int, string> func1, func2, func3, ...;

int iq = ...;
string result = iq match
{
    when <= 100: func1,
    when == 100: func2,
    when >= 100: func3,
    // ....
    default: funcx()
}(iq);

Meaning, the possibility to use the match-statement inside of expressions.

@HaloFour
Copy link

@Unknown6656 The proposal is that match is an expression, so of course you'd be able to use it within other expressions. You can think of it like a ternary op on steroids.

As for your specific example, there have been no proposed range patterns. Nor has there been a proposal to allow for only case guards with an implied wildcard pattern. So as of now your example would be:

string result = iq match (
    case * when iq < 100: func1,
    case * when iq == 100: func2,
    case * when iq > 100: func3,
    case *: funcx
)(iq);

@gafter
Copy link
Member

gafter commented Aug 10, 2017

Issue moved to dotnet/csharplang #812 via ZenHub

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants