RE: If...Then vs Select...Case

So… I just read the blog post about the pros and cons of using If…Then vs Select…Case and I think there’s more to say…

The article lists these as the reasons to use each one, but the first three are not limited to If…Else in my opinion:

  • Use If...Else when:
    • You only need to check if something is true or false.
    • You need to check many different things at the same time using “and” or “or”.
    • You need the most flexibility to handle all sorts of situations.
  • Use Select Case when:
    • You’re checking one thing against a list of possible values.
    • You want your code to be super clear and easy to understand.
    • You want a neat way to organize different options.

To do the first three in a select…case statement, you simply use True in the variable:

Select Case True
Case X = 5, y = 6 // treated as OR

Case x = 2 And y = 5 

Case aString = myFunction()

Case myBool = False

Case Else

End Select

Basically, if the clauses evaluate to True, False, or any other primitive, you can also use this form.

Personally I find this code a lot more readable than a long line of if…then…elseif statements.

8 Likes

Select Case or Switch() was created for a faster way to handle decisions on top of a value that could be “cached” and retested very fast, many times, specially if such value could be kept in a CPU register.

In this case below, the compiler can infer that expression should satisfy simple integer compares and store the result in a CPU register and compare it with 1 and jump if ok, then compare it with 3 and jump if ok and then just continue with the rest of the instructions of the block.

Select Case (expression)
Case 1
Case 3
Else
End Select

The construct Select Case True does not add any speed, functionality or clarity to the code, so I don’t like such style. But you know, style may be personal, so I don’t condemn others using it, but I don’t see myself using it. :wink:

I would keep the chain of ifs for your use case:

If x = 5 or y = 6 Then              // graph exploded

ElseIf x = 2 And y = 5 Then         // graph got bizarre  

ElseIf aString = myFunction() Then  // the label was ok

ElseIf Not myBool                   // myBool with a better name could suffice

Else

End If
1 Like

Wow.
I get that the Elseif stuff will work, but that’s pretty obscure… takes a few read throughs to follow what it does . (For me, anyhow)

The select case true construct is a lot clearer.

2 Likes

Well, I said some people would like weird constructs like “Select Case True” that I have no idea what Xojo does behind the scenes to handle it, and even think that such thing is clear, and prefer “x = 5, y = 6” when wanting to say “x = 5 or y = 6” and think that it’s clearer too.

As I don’t know if it causes an overhead (because it looks like causing), I prefer the clear instructions of what to do.

1 Like

Another thing not mentioned in the blog post, and correct me if I’m wrong, but the Cases get evaluated sequentially, so you can do this:

Select Case (expression)
Case Is < 10
Case Is < 20 (between 10 and 19.99999)
End Select
3 Likes

Yes, exactly as in an IF-ElseIf chain, but in your example a Select Case is more suitable, because the compiler could “cache” the result of the expression and reuse it in a fast way in all tests.

Being a convert from another coding universe, I’ve since taken up the use of Select Case over If... Else when I can.

It never occurred to me to try Select Case True.

Thank you Greg, this is very helpful.

Just to avoid people becoming confuse because you missed the comment mark:

Select Case (expression)
Case Is < 10
Case Is < 20      // (between 10 and 19.99999)
End Select
1 Like

I use SELECT CASE this way a lot because it’s easier to read, particularly when you are looking at ranges.

However I tend to only use it in preference to IF THEN, ELSEIF when I know I have quite a few cases to consider in advance.

Using IF gives a little more flexibility when you need to combine conditions, or nest combinations. Of course, sometimes I just embed IF THEN, ELSEIF, END IF within the CASEs.

Horses for courses really; whatever works and is easiest to read, unless speed and optimisation is vital.

FWW If…then is also much faster than Select…case

my advice for if then else and select case:
do not expand source code there, bundle it and use function/method calls instead
to have that conditions overseeable and understandable.
let conditions as possible outside of methods.

It depends on the task, your goals, needs, and the complexity of the expressions:

// #1: Simple expression, it's readable (comments exist to make it cleaner), then just do it: 

If currentValueIsInvalid And invalidValue < 999999 Then  // aberrative value
  // whatever, but faster
End

// #2: It's simple, let's just complicate because I don't care about performance
//     and unnecessary code (same as above, but with a function): 

If IsAberrative(currentValueIsInvalid, invalidValue) Then
  // whatever, but slower and more complex to build
  // needing extra code and parametrization 
End

Function IsAberrative(currentValueIsInvalid As Boolean, invalidValue As Double) As Boolean
  Return (currentValueIsInvalid And invalidValue < 999999)
End

i meant the between

if ... then
 64 kByte Source Code
else
 64 kByte Source Code
end if

better (and especially at cascading if then)

if ... then
 DoSomethingA()
else
 DoSomethingB()
end if

Large pieces of code? Sure, when possible encapsulating them makes the code much more readable.

I would love local functions, that’s sad that Xojo don’t let us to write them.
Small repetitive helpers used just in the current context, I always complain about it. Like:

// Just a silly example to demonstrate the need

// TwoCircleArea is a Xojo function object listed on the navigator
Function TwoCircleArea(r1, r2 As Double) As Double

  // CircleArea is a local function, 
  // just a piece of code of the TwoCircleArea code
  // It's just visible for the current code, not outside
  Function CircleArea (radius As Double) As Double
    Return (radius * radius * 3.1415926)
  End

  Return CircleArea(r1)+CircleArea(r2)

End

Or

// Better if the order does not matter

Function TwoCircleArea(r1, r2 As Double) As Double

  Return CircleArea(r1)+CircleArea(r2)

  Function CircleArea (radius As Double) As Double
    Return (radius * radius * 3.1415926)
  End

End
2 Likes

do we have a issue to vote on?

the feature to share variables from parent method is also nice to have.

It’s an old complaint. Maybe. Never got attention for it. I’ll check.

Couldn’t find it, found just mentions about the subject: Rick mentions Local Function

2 Likes

Thanks - this is an excellent discussion of the coding options. It is helpful.