简体   繁体   中英

Should I use a variable for a switch statement or a return statement when using a switch in a property to retrieve a value?

Should I save a result from a switch statement before returning it? Or should I return the value in the switch when I get it? Is there one way over another that is better style?

With a temporary variable:

      public double xMax {
      get {
           double val = 0.00f;
           switch(x_option) {
                case 0:
                     val = priMax;
                     break;
                case 1:
                     val = rfMax;
                     break;
                case 2:
                     val = pwMax;
                     break;
           }

           return val;
      }
 }

With return statement:

 public double xMax {
      get {
           double val = 0.00f;
           switch(x_option) {
                case 0:
                     return priMax;
                case 1:
                     return rfMax;
                case 2:
                     return pwMax;
           }
      }
 }

Is there a performance difference and/or cleanup?

Personally I prefer the second form. It makes it immediately clear that as soon as you've got to the return statement, you're done. With the extra variable version, you have to look through the rest of the code to see if anything else will happen.

The dogma around a single point of return made sense in C, where you'd want to make sure you did all your manual clean-up etc - but in a world where you have to consider the possibility of exceptions anyway , and the garbage collector handles most of the cleanup, with try/finally handling the rest, I find there are a lot of cases where insisting on a single exit point makes the code significantly harder to read - particularly around cases where you can determine the result right at the start of the method (eg "if the input string is empty, the result is always going to be 0 - so just return it there).

EDIT: Just to be clear, in your situation I don't think it makes much difference. But this is the kind of code where single point of return gets messy:

 public int DoSomething(string input1, string input2)
 {
     // First simple case
     if (input1 == null || input2 == null)
     {
         return -1;
     }

     // Second simple case
     int totalLength = input1.Length + input2.Length;
     if (totalLength < 10)
     {
         return totalLength;
     }

     // Imagine lots of lines here, using input1, input2 and totalLength
     // ...
     return someComplicatedResult;
 }

With a single point of return, this would become:

 public int DoSomething(string input1, string input2)
 {
     int ret;

     // First simple case
     if (input1 == null || input2 == null)
     {

         ret = -1;
     }
     else
     {
         // Second simple case
         int totalLength = input1.Length + input2.Length;
         if (totalLength < 10)
         {
             ret = totalLength;
         }
         else
         {
             // Imagine lots of lines here, using input1, input2 and totalLength
             // ...
             ret = someComplicatedResult;
         }
     }
     return ret;
 }

I would definitely rather read the first form than the second:

  • More nesting generally makes code harder to understand. It's hard to remember where you've got to
  • In the first form, you can clearly tell - without reading any more code - that if you get to the base cases, you're done. There's not going to be any side effect after the complicated code; we're just going to return. In the second code, you have to mentally skip over the "else" blocks to work out what's happening. You're looking over more code to work out the path.

Well, the most important thing is that you don't mix them.

One motivation for the first form is that it has a single point of exit from the getter. If the code is more complex than in the examples, that could be useful, but in a simple example like this it doesn't really matter.

The simplicity of the second form is a good argument as long as the code is as simple as in the example.


Your second example doesn't compile as it is now, as the code could reach the end of the property without returning anything. In the first case you can set the variable to a default value before the switch, for the second case you should use a default option in the switch, and you don't need the variable at all:

public double xMax {
  get {
    switch(x_option) {
      case 0:
        return priMax;
      case 1:
        return rfMax;
      case 2:
        return pwMax;
      default:
        return 0d;
    }
  }
}

It's a matter of taste but I prefer to have a single point of return when possible. It's easier to debug, let you check for pre and post when using code contracts more clearly.

This question is two generation old. But I'll answer it as this question used to haunt me too.


Here's what you are looking at: Syntax A and Syntax B .

What should you be looking at: Consistency of syntax in your code throughout.

Pick one style and stick to it. This can be dictated by personal choice, team's choice, boss' choice etc. Bothering about performance until you have bottleneck is putting cart before horse.


As a general consequence of code and complexity accumulation, if you are faced with switch statement, then someone wrote bad code somewhere and tried to handle a lot of things in one yarn ball of a code.

Case in point: An API call that returns JSON which sends back 5 different values in an array and you need to figure out how to handle it or what data to pick as per your need.


Most times you should break your code into little chunks as soon as there are possibilities of multiple returns or ifs.

Take Jon Skeet's code for example:

public int DoSomething(string input1, string input2)
 {
     int ret;

     // First simple case
     if (input1 == null || input2 == null)
     {

         ret = -1;
     }
     else
     {
         // Second simple case
         int totalLength = input1.Length + input2.Length;
         if (totalLength < 10)
         {
             ret = totalLength;
         }
         else
         {
             // Imagine lots of lines here, using input1, input2 and totalLength
             // ...
             ret = someComplicatedResult;
         }
     }
     return ret;
 }


Let's see if we can make code a bit more readable first.

 private int someComplicatedTask(string input1, string input2){ // Second simple case int ret = 0; int totalLength = input1.Length + input2.Length; if (totalLength < 10) { ret = totalLength; } else { // Imagine lots of lines here, using input1, input2 and totalLength // ... ret = someComplicatedResult; } return ret; } public int DoSomething(string input1, string input2) { return input1 == null || input2 == null ? -1 : someComplecatedTask(...); } 

This should make you wonder, 'Why did you call DoSomething when there was a chance that inputs can be null?'.

Notice how the problem is not solved yet. All I have achieved is make the code look better.

Here's how I would have dealt with it regarding if conditions:

Condition for null inputs will be moved out to a sanitizing function. Or call will made only when inputs are not null.

 ... if(input1 != null && input2 != null){ output = DoSomething(input1, input2); } ... public int DoSomething(string input1, string input2) { int len = input1.Length + input2.Length; return len < 10 ? len : someComplecatedTask(input1, input2); } private int someComplicatedTask(string input1, string input2){ // Imagine lots of lines here, using input1, input2 // ... return someComplicatedResult; } 

So, code looks more manageable now. There're only two pathways that code can walk on, and everything is alright.


Now let's look at your first code snippet.

 public double xMax { get { double val = 0.00f; switch(x_option) { case 0: val = priMax; break; case 1: val = rfMax; break; case 2: val = pwMax; break; } return val; } } 

Off the top of my head, this is bad for two reasons:
1. Some time in future, x_option gains another value, you will be hunting every get {} down for appropriate change.
2. Get {} should be straight forward. Set {} should contain conditions for setting appropriate values.

So code should have looked liked this:

 public double xMax { set { double val = 0.00f; switch(value) { case 0: val = priMax; break; case 1: val = rfMax; break; case 2: val = pwMax; break; } xmax = value * val; // say // This makes break better in switch. } get { return xmax; } } 

Since, after breaking out of your case, you can do some more (common for all cases) operations, then this is better than returning. This example with respect to get one is better since, while setting you don't know the value, so you need a decision tree.

But while getting, your object exactly knows what it contains and returns gleefully what's asked.

Now, your second code example shouldn't make sense at all. Deciding what to return is not object's duty. It should return what it has pronto.

And while setting, you shouldn't return forcefully anyway.

I hope this clears some doubts and raises few more questions since there's a lot left to learn.

At my first programming classes at Military University of Technology in Warsaw, Dr. Eng. Zbigniew Wesołowski stated, that the function can only have one returning point. It was introduction to programming in ANSI-C, but he also told, that we should never forget that, as it is a universal rule, no matter what language we'll have to develop in. What is more, like a despot, he stated that one will never pass his exam, if he try - even once - to use goto statement, return in the middle of a function, or modify iterator inside a for loop.

It is an aged dilemma, whether to return in the middle, or not. Some claim it makes code clearer, other that it is not elegant and should be avoided. In my experience I've noted, that multiple returns most often occur in java code, while c, c++ and also c# programmers rather avoid that. That's not a rule, just an observation.

Another observation is that java language encourages compact syntax. Java IDE's (ex. eclipse) often have default formatter set to put opening brace at same line (just a trivial example). Multiple returns align with that approach allowing further compacting the code.

Visual Studio in opposite puts opening brace on new line as an only character. It encourages clear, bold syntax, with long files, many blank or single character lines. I do not know which is better, if any.

Basically I write C# at classes at university and at home. And then I prefer that long files with blank lines.

In my company, I write java code, and then I prefer more compact style, that I get used to. In company we use checkstyle to maintain good code quality by uniform styling. And through many years of company existence there has been rule in checkstyle that disallows multiple returning at all.

I've seen a post at stackoverflow where some one issued that it has a performance impact. In an answer he's got results of a simple benchmark checking that. And in fact there was no big difference.

In my coding practice I rather avoid multiple returns. But your overall decision would depend on your personal taste, experience, habits, beliefs, and maybe quality requirements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM