Use of return keyword in code block - c#

What is the difference between saying:
if (abc == "a")
{
// do something here...
return;
}
and the same as above, but without the return keyword?
I am a C# coder and I know that the return keyword followed by a type or variable returns that item, but in the above context, return seems to be just to exit the code block but does it make any functional or performance change on the code?
Thanks

"return" exits from the function, not just the enclosing code block. So if your code block was in the context of a function, like so (I don't know C# so I'm using Java syntax):
int thisIsAFunction(int a) {
if (abc == "a")
{
// do something here...
return 1;
}
// do something else here...
}
if abc == "a" then the "do something else here" will not run. But if you removed the return statement inside the if block, then it would run.

return statement exits the function immediately, so it might have performance benefits as the following code in the function would not be executed at all.

MSDN
The return statement terminates execution of the method in which it appears and returns control to the calling method. It can also return an optional value. If the method is a void type, the return statement can be omitted.
Example
//this would do nothing
public void method()
{
return;
}
//this would return true
//notice the return type of bool this means
//the method expects a true\false value
public bool method2()
{
return true;
}
public void test()
{
if(method2())
method()
}
Now if you ran test method2 would always return true and method1 would just end its processing

The return statement does exit the current method, not just the code block (for/while/if/etc). So it is useful for situations like the following:
public void MyMethod(object myObject)
{
if (myObject == null)
{
return; // exits method.
}
// do something with myObject
}
Additional info: I will point out, that many people prefer to have one exit point in a method, however, it can be useful to do something similar to the example here in some cases. I would always try to find ways to limit the number of return or exit points in your method.

In your case, no - but if you had other code after your 'if' statement that you only wanted to run if your statement was false (e.g. if abc != "a"), then the return allows you to bypass that and exit the function / method.

In a loop or case statement, you can use break to achieve this result. This doesn't work on if statements or code blocks in general though.
And yes, return exits the enclosing function.

Executing the return statement will make the execution jump out of the method. Without the return, it would simply go on with the next statement instead.

Yes, your method does not have return type in this case.
e.g.
public void Foo
{
if (abc == "a")
{
// do something here...
return;
}
// some other code
}
This is to say if abd = "a", then exit the method so that some other code won't be executed.

It can be a cleaner way of writing code. I typically do it in a guard clause at or near the beginning of a method. If you have an error condition, just "return" out of the method. It saves wrapping the rest of your work in an else block. Seems trivial, but it helps to reduce code complexity.

Related

How can I avoid code duplication in C# while and do-while loops?

I have a loop inside a C# method that has the following structure.
do
{
getUserInput();
if (inputIsBad)
{
doSomethingElse();
}
} while (inputIsBad);
alternately, with a while loop:
getUserInput();
while (inputIsBad)
{
doSomethingElse();
getUserInput();
}
But both methods use redundant code: the do-while has both an if statement and while loop checking the same condition; the while loop calls getUserInput() both before and inside the loop.
Is there a simple, non-redundant, non-ad hoc way to do what these method patterns do, either generally or in C# specifically, that only involves writing each basic component once?
Assuming that getUserInput(..) can be converted into a expression yielding a boolean value*..
while (getUserInput()
&& isBadInput()) {
doSomethingElse();
}
// Prompts for user input, returns false on a user-abort (^C)
private bool getUserInput() { .. }
Other variations (presumed without non-local state) shown in comments.
*Trivially, it can always be written as a wrapping function - see Local Functions, introduced in C#7. (There are other methods for the same effect, some of which I consider 'too clever'.)
// local function
bool getUserInputAlwaysTrue() {
getUserInput(); // assume void return
return true;
}
while (getUserInputAlwaysTrue()
&& isBadInput()) {
doSomethingElse();
}
This can be followed to pushing out the logic further, in some cases. The general premise holds: getUserInput() is always invoked prior to the next isBadInput().
// local function or member method
// Prompt for user input, returning true on bad input.
bool getCheckedUserInput() {
getUserInput(); // assume void return
return isBadInput();
}
while (getCheckedUserInput()) {
doSomethingElse();
}
do
{
getUserInput();
if (!inputIsBad) break;
doSomethingElse();
} while (true);
I would use a boolean variable, which you need to declare outside the body of the loop. That way you only need to run the inputIsBad check once. I have turned it into a method as well, since that seems more logical.
bool badInput = true; // Assume bad until checked -- failsafe.
do
{
getUserInput();
badInput = inputIsBad();
if (badInput)
{
doSomethingElse();
}
} while (badInput);
Building on user2864740's answer:
Assume getUserInput() can be converted into a function which returns true if the input is good and bad otherwise. Assuming its original return type wasn't boolean or void, return its original return value via an out or ref parameter depending on the case, e.g.
int originalReturnValue;
while (!getUserInput(out originalReturnValue))
{
doSomethingElse();
}
...
bool getUserInput<T>(out T output)
{
// method body
}

Which solution is best for breaking from a loop on user input?

I am currently learning programming and often I stumble upon tasks where you type into the console indeterminate amount of lines (each is a command that I have to filter out later in main with a switch or if-else statements) and at the end you type "END" to say that you will stop writing lines (often it results in end of the program but sometimes I have to print some final code). For the longest time I have used this solution to choose the needed selection:
while (true) {
var input = Console.ReadLine().Split();
if (input[0] == "END") break;
switch (input[0]) {
//Task specific cases
}
}
but today I randomly had an idea. (After I did some research) I could add the "END" case in the switch statement using the word return. The only problem is that because my code is in main it automatically ends the program. The solution is to transfer the code to another method but is this solution better or is it a bit overcomplicated?
*Here is what the second solution looks like:
static void Main(string[] args) {
Logic();
//Other stuff to do, if the task requires it
}
public static void Logic() {
while (true) {
var info = Console.ReadLine().Split();
switch (info[0]) {
case "END": return;
//Other task specific cases
}
}
}
**Sorry if the post is confusing to read, I am not very good with programming terminology.
This is another possible implementation:
public static void Logic()
{
bool exit = false;
do
{
var info = Console.ReadLine().Split();
switch (info[0])
{
case "END":
exit = true;
break;
}
}
while (!exit);
}
Any of the solutions, to use break or to return are correct, but have different behaviors. You can use the one that you find is better.
The break statement is used to terminate the loop or statement in
which it present. After that, the control will pass to the statements
that present after the break statement, if available. If the break
statement present in the nested loop, then it terminates only those
loops which contains break statement.
The return statement terminates the execution of the method and
returns the control to the calling method. It returns an optional
value. If the type of method is void, then the return statement can be
excluded.
You can read more here: https://www.geeksforgeeks.org/c-sharp-jump-statements-break-continue-goto-return-and-throw/

C# Function Return Error

I'm new to C# and while coding a small function facing this weird problem. While using the return statement I want to return to the calling function but instead it takes me to a level before in the recursion and never exits from the recursive function.
My code is as follows:
private void findrel(String from, String to, List<RelAttr> relation)
{
String var;
List<RelAttr> temp = new List<RelAttr>();
for (int i = 0; i < relation.Count; i++)
{
if (Some Condition)
{
if (Another Condition)
{
//Do Something
paths.Add(Something);
return;
}
else
{
//Capture some value in var
paths.Add(Something);
//Move to Temp
temp.AddRange(relation);
//Remove Active Entry From Temp
temp.RemoveAt(i);
//Call with Newlist (temp)
findrel(var, to, temp);
}
}
}
//Remove Last Entry when recursion unwinds
paths.RemoveAt(paths.Count - 1);
}
I'm calling this function normally from the other function such as:
findrel(from, to, relations);
And I want the return statement to return to this function and not to a level before in the recursion. Any ideas?
The return statement will always return to the caller, and when you are using recursion this will include returning to the level above, and will not jump back to the original caller.
If you want to get right out of findrel then you will have to do something like return a flag so that the previous level knows that it should just return back to its caller and not do any more processing.
So the code will still unwind from all the calls to findrel but you will have effectively stopped processing.
Usually with recursive functions you have a terminating condition and that causes all levels of the returning function to return and this will return you to the caller. One suggestion might be to return a Boolean and terminate the recursion if that value is say false. The you can add that condition to the terminating condition of your loop and your function will exit all levels.

Why does this compile

I have trouble understanding what the following code means (and partly, why it even compiles).
We have the following snippet:
if (true) return;
{
... // Unreachable code detected
}
Why does this even compile?
Am I correct in thinking that the compiler assumes an else in this construct? If not, how does it work?
I think it must be logically equivalent to
if (true)
return;
else
{
...; // Unreachable code detected.
}
I'm in doubt, because the compiler doesn't seem to interpret the following as an if-else
if (condition)
{
...
}
{
...
}
It does compile, but the second block gets executed no matter what.
Is this behavior explicitly stated in the C# specs?
It doesn't assume an else here, it's just that any code of the form:
if(condition)
{
code A
return;
}
code B
is logically equivalent to:
if(condition)
{
code A
return;
}
else
{
code B
}
Because code B will only ever be reached if condition evaluates to false.
Your confusion might also be coming from having a braced block of code that is not preceded by a keyword.
code A
{
code B
}
This is perfectly legal; code blocks do not require control flow keywords, and you can nest your code within braces wherever you like. While it's not terribly common, it's legal. Note that it does create a new variable scope in your code, and (just like all other code blocks) code outside of these blocks will not be able to access any variables declared within the block.
For example:
code A
{
int foo = 10;
code B
}
int bar = foo; // compiler error, as foo is not a variable within this scope
While not advisable, you could use this to declare two identically-named but different variables:
{
int foo = 10;
code A
}
{
string foo = "bar";
code B
}
Your confusion comes from the fact that you can include anything in arbitrary { }. For example:
{
Console.WriteLine(a);
{
a = 6;
}
}
{
Console.WriteLine(a);
}
This is perfectly valid and all the curly braces are perfectly pointless. But still valid!
if (true) return;
{
... // Unreachable code detected. WTF?
}
is equivalent of
if (true)
return;
... // Unreachable code
no else is implied there.
Answer in the comments:
if (true) return;
// whatever is after the previous statement will never be executed
// because the previous statement will always return
{
// this is not automatically added to the "else" part of the previous if
// this is just a code block with additional braces, which are not
// required but valid.
}
The code after the return is unreachable. The condition true is always, err, true.
It's a logic issue, not syntax. Therefore the compiler won't spot it.
As for your third example, it breaks the rules of (most if not all) programming languages and therefore the compiler will spot it and throw an error.
No. The ';' after your if doesn't close the truepart. It closes all the if. So the block after is reachable code. If your first test failed. The compiler didn't introduce an else. You think that because it's equivalent, but in fact it's not an else.

Using a Goto to enhance the DRY principle and code clarity: a good idea?

I have some code that is structured like the following:
if (someStatement)
{
//...
if (SomeOtherStatement)
{
//..., possibly more cases like this
}
else
{
//goto warning;
//would otherwise repeat
//the MessageBox.Show here
}
}
else
{
//goto warning;
}
//...
warning:
MessageBox.Show("some warning");
As i abhor copying code, is this one of the few useful applications of goto or is there a better structure i can use?
What about this?
if (someStatement)
{
//...
if (SomeOtherStatement)
{
//..., possibly more cases like this
return; // in the inner-most case
}
}
MessageBox.Show("some warning");
Yes, but only if by goto you mean "create a function and call it multiple times".
the best approach depends on what the rest of your code looks like. if the code shown is the last code in that method:
if(someStatement) {
// ...
if(SomeOtherStatement)
{
// a couple of lines of code
return; // !
}
}
MessageBox.Show("someWarning");
if not, you probably have to retort to something like this:
if(someStatement) {
// ...
if(SomeOtherStatement)
{
// a couple of lines of code
}
else
{
showWarning("not someOtherStatement");
}
}
else
{
showWarning("not someStatement");
}
I personally consider centralized error handling as "almost the only case" where goto is acceptable. However, for a better structure, I would put the label fully outside of the else, at the very end of your function.
Are you displaying the same error message on both lines? Then you should write a function that calls just that line and call that function on both occasions.
if (someStatement)
{
//...
if (SomeOtherStatement)
{
//..., possibly more cases like this
}
else
{
showError();
}
}
else
{
showError();
}
BTW: this is a bad example, it can be solved with a single else-branch catching the error. Here is a better one:
if (!doSomething())
{
showError();
}
doSomethingElse();
if (!anotherCall())
{
showError();
}
If you are going to get into a deep nasty error testing statement like you have, then you might want to consider wrapping it with a single try/catch, and throw the appropriate application specific exceptions from within the if statement, and catch those specific exceptions in the catch block, letting all the others go to be caught further up the chain.
Exceptions are the proper way to handle errors in .NET, throw them, but use them wisely:
try
{
if (someStatement)
{
//...
if (SomeOtherStatement)
{
//..., possibly more cases like this
}
else
{
throw new MyException();
//would otherwise repeat
//the MessageBox.Show here
}
}
}
catch(MyException e)
{
MessageBox.Show(e.Message);
// log the exception, if necessary
}
finally
{
// tidy up
}
With the exception you get a strongly typed answer to what went wrong which you can easily implement into logging systems.
Since (starting with FrameWork 1.1) logical-and "&&" : "only evaluates its second operand if necessary."
What's wrong with :
if(someStatement && someOtherStatement)
{
// more whatever
}
else
{
// raise an exception, call a method, show messagebox, whatever
}
Depending on the complexity of logical evaluation going on if the first clause evaluates to true : and you, possibly, implement lots of other tests, any number of which could result in errors : all of which you want handled in the identical way : I'd consider it mandatory to either raise a specific exception, call a method to handle the error, or put the whole thing in a try-catch block (which can be quite ugly if there's a lot of code).
A low-down-dirty-sneaky method I would use if it was a reasonable presumption that the possibility of error was quite remote 99% of the time the code was called : I'd set a boolean flag to reflect an error state : evaluate it on completion of the complex code block, and do what needed to be done : of course if your code branches off somewhere as a result of these internal evaluations : that would not be a good thing.
I think goto is a bad idea. If you have to jump, throw an exception, as proposed by joshcomley; if you just want to output the warning message, but continue without a jump, call a method.

Categories

Resources