8

I recently switched from VB to C#. One thing that I noticed was that in C#, I have problems using comparisons as part of the case. I am not sure how to explain it in words, so here is an example of what I am trying to do.

In VB, my code looks like this and works perfectly fine.

    Select Case ExamScore
        Case Is >= 90
            Grade = "A"
        Case Is >= 80
            Grade = "B"
        Case Is >= 70
            Grade = "C"
        Case Is >= 60
            Grade = "D"
        Case Else
            Grade = "F"
    End Select

In C# on the other hand, Visual Studio tells me that ">=" is an invalid expression.

    switch (examScore)
    {
        case >= 90: grade = "A"; break;
        case >= 80: grade = "B"; break;
        case >= 70: grade = "C"; break;
        case >= 60; grade = "D"; break;
        default: grade = "F"; break;
    }

Am I doing something wrong here, or is it simply not possible to do this in C#?

Thank you very much in advance!

Dhaval Panchal
  • 612
  • 4
  • 12
  • 32
user2763890
  • 85
  • 2
  • 6
  • @Dominic - Although this is the same problem, I think none of these are proper duplicates, because here the code cannot be sanely written as `switch`/`case`. – Kobi Sep 10 '13 at 07:22
  • jyparask's answer is most direct conversion - the VB 'Select Case' is simply a very different construct than the C# 'switch' - they are only equivalent for exact integer or string matches. – Dave Doknjas Sep 10 '13 at 14:14

5 Answers5

12

Top part of this answer is true for C# versions before 7. See below the line for an update for version 7

It's not possible. C# switches can only switch on exact equality:

Each case label specifies a constant value. Control is transferred to the switch section whose case label contains a constant value that matches the value of the switch expression,

You could replace it with a stack of if/else statements, or if you prefer, you can make something that looks quite compact, but some may frown on - a nest of conditional operators:

grade = examScore >= 90 ? "A" :
        examScore >= 80 ? "B" :
        examScore >= 70 ? "C" :
        examScore >= 60 ? "D" :
        "F";

With C# 7, switch has been significantly enhanced, and it's now possible to apply more conditions within cases, although it's still not as "clean" as the VB version. E.g. you could do something like:

switch (examScore)
{
    case int es when es >= 90: grade = "A"; break;
    case int es when es >= 80: grade = "B"; break;
    case int es when es >= 70: grade = "C"; break;
    case int es when es >= 60; grade = "D"; break;
    default: grade = "F"; break;
}

Assuming that examScore is an int, this somewhat abuses the new "pattern matching on types" facility to be able to have something to say in the case clause, and then using the when clauses to apply arbitrary conditions to the newly introduced variable.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
3

Unlike in VB, the C# switch statement is something like "equals" check. So you might need a if else ladder in order to accomplish this.

You may try something like:

private char Grade(int marks)
{
    Dictionary<int, char> grades = new Dictionary<int, char> { { 60, 'A' }, { 50, 'B' } };
    foreach (var item in grades)
    {
        if (marks > item.Key)
            return item.Value;
    }
    return 'C';
}
Krishna Sarma
  • 1,852
  • 2
  • 29
  • 52
  • 3
    While this works, the order which the items in a `Dictionary` are returned is undefined. Better use a `OrderedDictionary` instead. – sloth Sep 10 '13 at 07:38
  • Agreed. You may try two separate lists too. Lists are lightweight than dictionaries IMO. – Krishna Sarma Sep 10 '13 at 07:45
2

It's not possible in C#.

Use a bunch of ifs instead.

sloth
  • 99,095
  • 21
  • 171
  • 219
1

You can have it all in nice function:

public string Grade(int examScore)
{
    if(examScore>=90)
    {
        return "A";
    }
    if(examScore>=80)
    {
        return "B";
    }
    if(examScore>=70)
    {
        return "C";
    }
    if(examScore>=60)
    {
        return "D";
    }
    return "F";
}
Giannis Paraskevopoulos
  • 18,261
  • 1
  • 49
  • 69
  • I'd have gone with `else` rather than `return` here... the example code in the original question doesn't `return`. – Marc Gravell Sep 10 '13 at 07:20
  • @MarcGravell I would rather put it in a function. – Giannis Paraskevopoulos Sep 10 '13 at 07:21
  • Needs tweaking a little; for example grade "F" is never returned. – Bathsheba Sep 10 '13 at 07:24
  • 2
    Just to return the value in all the `if statements` why do you need a local variable at all? – Sriram Sakthivel Sep 10 '13 at 07:24
  • @Bathsheba I was returning "F", but now it may be more obvious. – Giannis Paraskevopoulos Sep 10 '13 at 07:26
  • Although this may be how to solve the problem, it doesn't answer the question imo – Sayse Sep 10 '13 at 07:27
  • @Sayse There is already an answer on the question, but there was a luck of an example of what to do. This is what my answer tries to fill. Is there any point at all having the same answer more than once? Damien has already provided an explanation. – Giannis Paraskevopoulos Sep 10 '13 at 07:31
  • I agree with you that answers should be unique (I don't answer questions unless I contribute something new like you have). OP's question only seems to ask why C# can't do similar to vb, I think Damien and Dominic's answer state what you have outlined and I'd imagine OP has the skill to create this themselves. As I said, just an opinion – Sayse Sep 10 '13 at 07:33
1

If you really want a switch statement you could use integer division

        int i = 69;
        switch (Math.Min(9, i / 10))
        {
            case 9: Grade = "A"; break;
            case 6: Grade = "B"; break;
        }
Sayse
  • 42,633
  • 14
  • 77
  • 146
  • Hey - you don't even need an obfuscator! I think if you write code that's hard to immediately understand then you had better be achieving something that's very awkward to do in a more direct way. – Dave Doknjas Sep 10 '13 at 14:17
  • @DaveDoknjas - Whilst still using a switch statement, this is the closest thing you can do. I don't think its that obfuscated, anyone familiar with simple mathematics would understand it – Sayse Sep 10 '13 at 14:25
  • If transparent clear logic is available, then that should be used instead. If someone had to maintain this code, there's a higher probability of error. – Dave Doknjas Sep 10 '13 at 14:40
  • @DaveDoknjas I'm not sure what your trying to prove here. This exact problem I had to do during my first university year in an effort to learn different C# syntax, I have upvoted other answers on this question so its not like i'd ever use this code. "If you *really* want a switch statement.." – Sayse Sep 10 '13 at 14:44
  • My only point is that 'clever' solutions are usually fragile and therefore bad ideas. It's better to have 'solid' solutions which are hard to break. – Dave Doknjas Sep 10 '13 at 14:50
  • The problem with this solution is that it relies on an implicit assumption that grades will be delineated by multiples of 10. What happens when the grade barrier for a B becomes 75, or when A+ is introduced for 95? – mrmillsy Mar 23 '15 at 01:22
  • @mrmillsy - I can't be certain but I think when I wrote it, I did so just to prove that it is doable with a switch statement. As I've said in comments, I don't think this should be used and there are much better coding alternatives. – Sayse Mar 23 '15 at 07:31
  • Fair point. I just wanted to highlight the reason it was bad [relying upon an implicit assumption]. Still, in fact a potentially useful technique to remember for other situations. – mrmillsy Mar 23 '15 at 20:29