Switch statement with returns -- code correctness

CSwitch StatementCorrectness

C Problem Overview


Let's say I have code in C with approximately this structure:

switch (something)
{
    case 0:
      return "blah";
      break;

    case 1:
    case 4:
      return "foo";
      break;

    case 2:
    case 3:
      return "bar";
      break;

    default:
      return "foobar";
      break;
}

Now obviously, the breaks are not necessary for the code to run correctly, but it sort of looks like bad practice if I don't put them there to me.

What do you think? Is it fine to remove them? Or would you keep them for increased "correctness"?

C Solutions


Solution 1 - C

Remove the break statements. They aren't needed and perhaps some compilers will issue "Unreachable code" warnings.

Solution 2 - C

I would take a different tack entirely. Don't RETURN in the middle of the method/function. Instead, just put the return value in a local variable and send it at the end.

Personally, I find the following to be more readable:

String result = "";

switch (something) {
case 0:
  result = "blah";
  break;
case 1:
  result = "foo";
  break;
}

return result;

Solution 3 - C

I would remove them. In my book, dead code like that should be considered errors because it makes you do a double-take and ask yourself "How would I ever execute that line?"

Solution 4 - C

Remove them. It's idiomatic to return from case statements, and it's "unreachable code" noise otherwise.

Solution 5 - C

Personally I would remove the returns and keep the breaks. I would use the switch statement to assign a value to a variable. Then return that variable after the switch statement.

Though this is an arguable point I've always felt that good design and encapsulation means one way in and one way out. It is much easier to guarantee the logic and you don't accidentally miss cleanup code based on the cyclomatic complexity of your function.

One exception: Returning early is okay if a bad parameter is detected at the beginning of a function--before any resources are acquired.

Solution 6 - C

Keep the breaks - you're less likely to run into trouble if/when you edit the code later if the breaks are already in place.

Having said that, it's considered by many (including me) to be bad practice to return from the middle of a function. Ideally a function should have one entry point and one exit point.

Solution 7 - C

I'd normally write the code without them. IMO, dead code tends to indicate sloppiness and/or lack of understanding.

Of course, I'd also consider something like:

char const *rets[] = {"blah", "foo", "bar"};

return rets[something];

Edit: even with the edited post, this general idea can work fine:

char const *rets[] = { "blah", "foo", "bar", "bar", "foo"};

if ((unsigned)something < 5)
    return rets[something]
return "foobar";

At some point, especially if the input values are sparse (e.g., 1, 100, 1000 and 10000), you want a sparse array instead. You can implement that as either a tree or a map reasonably well (though, of course, a switch still works in this case as well).

Solution 8 - C

>What do you think? Is it fine to remove them? Or would you keep them for increased "correctness"?

It is fine to remove them. Using return is exactly the scenario where break should not be used.

Solution 9 - C

I would say remove them and define a default: branch.

Solution 10 - C

If you have "lookup" type of code, you could package the switch-case clause in a method by itself.

I have a few of these in a "hobby" system I'm developing for fun:

private int basePerCapitaIncomeRaw(int tl) {
	switch (tl) {
		case 0:		return 7500;
		case 1:		return 7800;
		case 2:		return 8100;
		case 3:		return 8400;
		case 4:		return 9600;
		case 5:		return 13000;
		case 6:		return 19000;
		case 7:		return 25000;
		case 8:		return 31000;
		case 9:		return 43000;
		case 10:	return 67000;
		case 11:	return 97000;
		default:	return 130000;
	}
}

(Yep. That's GURPS space...)

I agree with others that you should in most cases avoid more than one return in a method, and I do recognize that this one might have been better implemented as an array or something else. I just found switch-case-return to be a pretty easy match to a lookup table with a 1-1 correlation between input and output, like the above thing (role-playing games are full of them, I am sure they exist in other "businesses" as well) :D

On the other hand, if the case-clause is more complex, or something happens after the switch-statement, I wouldn't recommend using return in it, but rather set a variable in the switch, end it with a break, and return the value of the variable in the end.

(On the ... third? hand... you can always refactor a switch into its own method... I doubt it will have an effect on performance, and it wouldn't surprise me if modern compilers could even recognize it as something that could be inlined...)

Solution 11 - C

Wouldn't it be better to have an array with

arr[0] = "blah"
arr[1] = "foo"
arr[2] = "bar"

and do return arr[something];?

If it's about the practice in general, you should keep the break statements in the switch. In the event that you don't need return statements in the future, it lessens the chance it will fall through to the next case.

Solution 12 - C

For "correctness", single entry, single exit blocks are a good idea. At least they were when I did my computer science degree. So I would probably declare a variable, assign to it in the switch and return once at the end of the function

Solution 13 - C

Interesting. The consensus from most of these answers seems to be that the redundant break statement is unnecessary clutter. On the other hand, I read the break statement in a switch as the 'closing' of a case. case blocks that don't end in a break tend to jump out at me as potential fall though bugs.

I know that that's not how it is when there's a return instead of a break, but that's how my eyes 'read' the case blocks in a switch, so I personally would prefer that each case be paired with a break. But many compilers do complain about the break after a return being superfluous/unreachable, and apparently I seem to be in the minority anyway.

So get rid of the break following a return.

NB: all of this is ignoring whether violating the single entry/exit rule is a good idea or not. As far as that goes, I have an opinion that unfortunately changes depending on the circumstances...

Solution 14 - C

I say remove them. If your code is so unreadable that you need to stick breaks in there 'to be on the safe side', you should reconsider your coding style :)

Also I've always prefered not to mix breaks and returns in the switch statement, but rather stick with one of them.

Solution 15 - C

I personally tend to lose the breaks. Possibly one source of this habit is from programming window procedures for Windows apps:

LRESULT WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_SIZE:
            return sizeHandler (...);
        case WM_DESTROY:
            return destroyHandler (...);
        ...
    }
    
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

I personally find this approach a lot simpler, succinct and flexible than declaring a return variable set by each handler, then returning it at the end. Given this approach, the breaks are redundant and therefore should go - they serve no useful purpose (syntactically or IMO visually) and only bloat the code.

Solution 16 - C

I think the breaks are there for a purpose. It is to keep the 'ideology' of programming alive. If we are to just 'program' our code without logical coherence perhaps it would be readable to you now, but try tomorrow. Try explaining it to your boss. Try running it on Windows 3030.

Bleah, the idea is very simple:


Switch ( Algorithm )
{

 case 1:
 {
   Call_911;
   Jump;
 }**break**;
 case 2:
 {
   Call Samantha_28;
   Forget;
 }**break**;
 case 3:
 {
   Call it_a_day;
 }**break**;

Return thinkAboutIt?1:return 0;

void Samantha_28(int oBed)
{
   LONG way_from_right;
   SHORT Forget_is_my_job;
   LONG JMP_is_for_assembly;
   LONG assembly_I_work_for_cops;

   BOOL allOfTheAbove;

   int Elligence_says_anyways_thinkAboutIt_**break**_if_we_code_like_this_we_d_be_monkeys;

}
// Sometimes Programming is supposed to convey the meaning and the essence of the task at hand. It is // there to serve a purpose and to keep it alive. While you are not looking, your program is doing  // its thing. Do you trust it?
// This is how you can...
// ----------
// **Break**; Please, take a **Break**;

/* Just a minor question though. How much coffee have you had while reading the above? I.T. Breaks the system sometimes */

Solution 17 - C

Exit code at one point. That provides better readability to code. Adding return statements (Multiple exits) in between will make debugging difficult .

Solution 18 - C

Simply define variable and return it at last of the switch statement and we can also remove default statement by setting variable= default value.

Ex:

switch(someVariable)
{
case 'a':
 return a;
 break;
case 'b':
 return b;
 break;
default:
 return c;
}

solution:

    $result = c; //for default value
    switch(someVariable)
    {
    case 'a':
     $result = a;
     break;
    case 'b':
     $result = b;
     break;
    }
    return $result; //simply return $result
  • This will lead to reduce your return statement.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhoubysoftView Question on Stackoverflow
Solution 1 - CkgiannakakisView Answer on Stackoverflow
Solution 2 - CNotMeView Answer on Stackoverflow
Solution 3 - CHank GayView Answer on Stackoverflow
Solution 4 - CStephenView Answer on Stackoverflow
Solution 5 - CAmardeep AC9MFView Answer on Stackoverflow
Solution 6 - CPaul RView Answer on Stackoverflow
Solution 7 - CJerry CoffinView Answer on Stackoverflow
Solution 8 - COscarRyzView Answer on Stackoverflow
Solution 9 - CBellaView Answer on Stackoverflow
Solution 10 - CErkView Answer on Stackoverflow
Solution 11 - CVivin PaliathView Answer on Stackoverflow
Solution 12 - CSteve SheldonView Answer on Stackoverflow
Solution 13 - CMichael BurrView Answer on Stackoverflow
Solution 14 - CThomas KjørnesView Answer on Stackoverflow
Solution 15 - CMacView Answer on Stackoverflow
Solution 16 - CCruentos SolumView Answer on Stackoverflow
Solution 17 - CantishView Answer on Stackoverflow
Solution 18 - CYagnesh PrajapatiView Answer on Stackoverflow