58

I'm using an Or statement in my case expression.

Even though I have a value within this range, it didn't find a match. Why not?

Example Code:

Select Case 2
    Case 0
        ' Some logic

    Case 1
        ' Some other logic

    Case 2 Or 3
        Console.WriteLine("hit")

 End Select

With the above I would assume that hit would be printed, but that's not the case.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Llyle
  • 5,980
  • 6
  • 39
  • 56

6 Answers6

101

Use the comma operator to delimit case statements

Select Case 2
    Case 0,1,2,3
        Console.WriteLine("hit")
 End Select
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • my intent is not for case 0 and 1 to fall through. But the comma is what I was after. – Llyle Feb 17 '09 at 01:27
  • 3
    -1, because it does not answer the question as stated. It rather gives an alternative solution to the one attempted by the questioner. The question is: how does VB interpret the OR operator in a Select statement? Otherwise, the question must be edited to match the answer. But I would not suggest that, because @JohnT gave the correct answer. – Geoffrey Jan 28 '10 at 19:14
  • @Geoffrey, umm, the OP both accepted my answer and acknowledged it was what they were after. – JaredPar Jan 28 '10 at 19:21
  • I know. @vanslly must restate the question, but then @JohnT, who answered correctly, loses the points. – Geoffrey Jan 28 '10 at 19:47
  • 3
    @Geoffrey, IMO it's more important to understand the OP's intentions than it is to answer exactly what he asks. It's the same concept between the letter of the law vs the spirit of the law. Both are correct, but I think the spirit of the law (ie his intentions) is more correct. – goku_da_master Nov 09 '11 at 16:37
24

As Jared said, you need to use the comma operator to delimit case statements.

The Or you were doing is a bitwise OR, resulting in it being "3". Amusingly, "2 AND 3" would probably have worked for your specific case.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John T
  • 470
  • 3
  • 13
21

JaredPar has it right but you can also use the To construct

Select Case 2
    Case 0,1
    Case 2 To 3
        Console.WriteLine("Hit")
End Select

This would be 0 or 1 do nothing, 2 or 3 print Hit...The To construct is a range...

Here's the MSDN

Restore the Data Dumps
  • 38,967
  • 12
  • 96
  • 122
  • True, and I was using the To keyword, but it's slightly hacky because if say 2 and 3 were Enum vals and the enum gets refactored without taking this use into consideration - which if it's in some class deep in the bowels of a large system - then you have some unexpected breaks ;) – Llyle Feb 17 '09 at 02:37
10

Edit: It appears I was wrong in assuming that VB.NET doesn't allow Case ORing. I was thinking in C# and IL and it appears I was wrong.

However, as someone pointed out, the reason your code did not work was because Case 2 Or 3 was evaluating 2 Or 3 as a bitwise or and hence evaluating to Case 3.

For clarification:


       2 binary = 0000 0010
       3 binary = 0000 0011
  2 Or 3 binary = 0000 0011 (= 3)

  Select Case 2
     Case 0            '--> no match

     Case 1            '--> no match

     Case 2 Or 3       '(equivalent to Case 3  --> no match)
   End Select

However, I feel that I should point out that for the sake of performance, one should not use such constructs. When the compiler encounters Select statements (switch in C#) it will try to compile them using lookup tables and the switch MSIL instruction but in the case where you have something like Case 1,2,11,55 the compiler will not be able to convert that to a lookup table and it will have to use a series of compares (which is like using If.. Else).

The point is that in order to really take advantage of the Select statement, the cases should be designed with that in mind. Otherwise, the only benefit is code readability.

A well designed switch is an O(1) operation whereas an poorly designed one (which is equivalent to a series of If..Then..Else statements) is an O(n) operation.

user67143
  • 317
  • 1
  • 4
  • Thanks, that allows my mind to rest now. Reading the code logically didn't give me any hints that I was doing something wrong. – Llyle Feb 17 '09 at 01:24
  • I'm glad you were able to find the answer to the problem you were looking to solve and I hope the clarifications I added to my answer will help you craft better Select statements :) – user67143 Feb 17 '09 at 01:40
3

This will allow you to perform "something" in the case of 0, "something else" in the case of 1, "hit" in the case of 2 or 3 or "hit else" otherwise.

Select Case 2
    Case 0
        Console.WriteLine("something")
    Case 1
        Console.WriteLine("something else")
    Case Is 2 To 3
        Console.WriteLine("hit")
    Else
        Console.WriteLine("hit else")
 End Select
achinda99
  • 5,020
  • 4
  • 34
  • 42
0

Most or all of these answers are ignoring the purpose of fall-through (or Goto Case):

Not having to reuse code or create a special function just for a few areas in the same Select Case/If Tree so that you can avoid reusing code, like this Javascript.

These samples are pretty contrived. There are definitely ways to simplify this scenario, but a lot of times, there aren't.

let pay = 100, perks = '';
Switch (EmpObj.type) {
  Case 'Boss':
    pay = pay * 10;
    perks = '11 month vacation per year';
  Case 'Manager':
    pay = pay * 3; // This will make Boss pay * 30
  Case 'Employee':
    EmpObj.pay = pay;
    EmpObj.perks = perks;
    break;
  Case 'Intern':
    EmpObj.sendMessage("Go get some coffee.")
} 

In VB.net, the same code would be

dim pay = 100, perks = "";
Switch (EmpObj.type) {
  Case "Boss":
    pay = pay * 30
    perks = "11 month vacation per year"
  Case "Manager":
    pay = pay * 3
  Case "Employee":
  Case 'Intern':
    pay = 0
    EmpObj.sendMessage("Go get some coffee.")
End Select

EmpObj.pay = pay;
EmpObj.perks = perks;

Case, in simple situations, is easier to read and write than a comparative if-branch, but the fall-through is the best part.

There's a way that works now at least in Visual Basic 2017. It's not the prettiest though.

GoTo Case "[label]" and Goto [Case-label] still do not work.

The label (Number2 here) must be after the Case. That was the most disappointing part.

dim Value = "1"
Select Case Value
    Case "0"
       ' do nothing, example
    Case "1"
        MsgBox("one")
        GoTo Number2
    Case "2"
Number2:
        MsgBox("two")
    Case "boolean"
        MsgBox("three")
        ' just to show it won't fall through
End Select
Regular Jo
  • 5,190
  • 3
  • 25
  • 47