this is hard to answer without details, but in general, then...
- switches mostly end up as lookup tables. that means that it does not matter much what order you put the cases or what the switch variable's states look like.
- if you can fall-through conditions (no break between them) that can be much more efficient than if statments (eg if(x == 3 || x== 4) is much less efficient than case 3: 4: code in a switch) and its even better if that had an internal (if x==3 else..) because you can fall through that (case 3: code for 3: code for 3 and 4 ) with fewer logical tests and branches.
- switches are generally better if complicated cases are made into functions. Small simple code is not necessary. This is depends greatly on the code, so you can test both to see which is best.
You can roll your own switch/lookups with little arrays of boolean results:
x = array[booleanexpression]; where array has an element for 0 and 1
It is rare that you need this, but it can be useful when the switch variable is NOT integer type and you need the performance lift. You can make them bigger in some instances, like array [3] where the condition to get into it is like (x==value + x >= secondvalue) //possible results 0, 1, 2) see?
No, it isn't. Chained "if...else-if" is expressly the wrong way to think about switch.
how do I code switch-case the most efficiently
Depends on the switch and its context in the surrounding code.
You may find this article interesting, in particular its discussion of performance of while(...) { switch(...) { ... } }
in context of an interpreter: https://hal.inria.fr/hal-01100647/document
I'm actually pretty excited to share this because it contradicts the document I used to share.