Calling methods inside if() - C# - c#

I have a couple of methods that return a bool depending on their success, is there anything wrong with calling those methods inside of the IF() ?
//&& makes sure that Method2() will only get called if Method1() returned true, use & to call both methods
if(Method1() && Method2())
{
// do stuff if both methods returned TRUE
}
Method2() doesn't need to fire if Method1() returns FALSE.
Let me know there's any problem with the code above.
thank you.
EDIT: since there was nothing wrong with the code, I'll accept the most informative answer ... added the comment to solve the "newbie & &&" issue

I'll throw in that you can use the & operator (as opposed to &&) to guarantee that both methods are called even if the left-hand side is false, if for some reason in the future you wish to avoid short-circuiting.
The inverse works for the | operator, where even if the left-hand condition evaluates to true, the right-hand condition will be evaluated as well.

No, there is nothing wrong with method calls in the if condition. Actually, that can be a great way to make your code more readable!
For instance, it's a lot cleaner to write:
private bool AllActive()
{
return x.IsActive && y.IsActive && z.IsActive;
}
if(AllActive())
{
//do stuff
}
than:
if(x.IsActive && y.IsActive && z.IsActive)
{
//do stuff
}

As useful as they are, sequence points can be confusing. Unless you really understand that, it is not clear that Method2() might not get called at all. If on the other hand you needed BOTH methods to be called AND they had to return true, what would you write? You could go with
bool result1 = Method1();
bool result2 = Method2();
if (result1 && result2)
{
}
or you could go with
if (Method1())
if (Method2())
{
}
So I guess the answer to you question IMHO is, no, it's not exactly clear what you mean even though the behavior will be what you describe.

I would only recommend it if the methods are pure (side-effect-free) functions.

While, as everyone says, there's nothing "wrong" with doing things this way, and in many cases you're doing precisely what the language was designed for.
Bear in mind, however, that for maintainabilities sake, if Method2 has side effects (that is, it changes somethings state) it may not be obvious that this function is not being called (a good programmer will usually know, but even good programmers sometimes have brain farts).
If the short circuited expression has some kind of side effect, it may be more readable to seperate the statements, strictly from a maintenance perspective.

Looks good to me, multiple clauses in the if() block will short circuit if an earlier condition fails.

There shouldn't be any problem.
The normal behavior is that Method1() will execute, and if that returns true Method2() will execute, and depending on what Method2() returns, you may / may not enter the if() statement.
Now, this assumes that the compiler generates code that executes that way. If you want to be absolutely sure that Method2() doesn't execute unless Method1() returns true you could write it like this
if( Method1() )
{
if( Method2() )
{
// do stuff if both methods returned TRUE
}
}
But, I've always observed that your code will run as expected, so this is probably not necessary.

Nothin' wrong.
Actually...I wouldn't name them Method1 and Method2. Something more descriptive. Maybe passive sounding too (like StuffHasHappened or DataHasLoaded)

Looks good to me, but there are some caveats... This is NOT the kind of thing where blanket rules apply.
My guidelines are:
If the method names are short, and there are not too many of them, then it's all good.
If you have too many statements/method calls inside the if statement, you most likely are comparing more than one "set" of things. Break those "sets" out and introduce temporary variables.
"Too many" is subjective, but usually more than around 3
When I say "method names are short" I'm talking not just about the names, but the parameters they take as well. Basically the effort required for someone to read it. For example if( Open(host) ) is shorter than if( WeCouldConnectToTheServer ). The total size of all these items is what it comes down to.

Personally, I would consider
if(Method1() && Method2())
{
// do stuff if both methods returned TRUE
}
to be a bad practice. Yes, it works in the current environment, but so does
if(Method1())
{
if (Method2())
{
// do stuff if both methods returned TRUE
}
}
But will it work in ALL environments? Will future, possibly non-Microsoft, C# compilers work this way? What if your next job involves another language where both methods will always be called? I wouldn't rely on that particular construct not because it's wrong, but because it doesn't solve any serious problem, and it may become wrong in the future

Related

C# Boilerplate code

I'm thinking of building some generic extensions that will take a way all these null, throw checks and asserts and instead use fluent APIs to handle this.
So I'm thinking of doing something like this.
Shall() - Not quite sure about this one yet
.Test(...) - Determines whether the contained logic executed without any errors
.Guard(...) - Guards the contained logic from throwing any exception
.Assert(...) - Asserts before the execution of the code
.Throw(...) - Throws an exception based on a certain condition
.Assume(...) - Similar to assert but calls to Contract.Assume
Usage: father.Shall().Guard(f => f.Shop())
The thing is that I don't want these extra calls at run-time and I know AOP can solve this for me, I want to inline these calls directly to the caller, if you have a better way of doing that please do tell.
Now, before I'm researching or doing anything I wonder whether someone already done that or know of a tool that is doing it ?
I really want to build something like that and release it to public because I think that it can save a lot of time and headache.
Some examples.
DbSet<TEntity> set = Set<TEntity>();
if (set != null)
{
if (Contains(entity))
{
set.Remove(entity);
}
else
{
set.Attach(entity);
set.Remove(entity);
}
}
Changes to the following.
Set<TEntity>().Shall().Guard(set =>
{
if (Contains(entity))
{
set.Remove(entity);
}
else
{
set.Attach(entity);
set.Remove(entity);
}
});
Instead of being funny and try to make fun of other people, some people can really learn something about maturity, you can share your experience and tell me what's so good or bad about it, that I'll accept.
I'm not trying to recreate Code Contracts, I know what it is I'm using it everyday, I'm trying to move the boilerplate code that is written to one place.
Sometimes you have methods that for each call you have to check the returned object and is not your code so you can't ensure that the callee won't result a null so in the caller you have to perform null checks on the returned object so I thought of something that may allow me to perform these checks easily when chaining calls.
Update: I'll have to think about it some more and change the API to make the intentions clear and the code more readable.
I think that the idea is not polished at all and that indeed I went too far with all these methods.
Anyways, I'll leave it for now.
It sounds like you're describing something like Code Contracts: http://msdn.microsoft.com/en-us/devlabs/dd491992
If I understand what you're looking for, then the closest thing I've come up with is the extension method:
public static Chain<T>(this T obj, Action<T> act)
{
act(obj);
return obj;
}
This allows you to do the following:
Set.Remove(Set.FirstOrDefault(entity) ?? entity.Chain(a => Set.Add(a)));
As you can see, though, this isn't the most readable code. This isn't to say that Chain extension method is bad (and it certainly has its uses), but that Chain extension method can definitely be abused, so use cautiously or the ghost of programming past will come back to haunt you.

General function question (C++ / Java / C#)

This question is probably language-agnostic, but I'll focus on the specified languages.
While working with some legacy code, I often saw examples of the functions, which (to my mind, obviously) are doing too much work inside them. I'm talking not about 5000 LoC monsters, but about functions, which implement prerequisity checks inside them.
Here is a small example:
void WorriedFunction(...) {
// Of course, this is a bit exaggerated, but I guess this helps
// to understand the idea.
if (argument1 != null) return;
if (argument2 + argument3 < 0) return;
if (stateManager.currentlyDrawing()) return;
// Actual function implementation starts here.
// do_what_the_function_is_used_for
}
Now, when this kind of function is called, the caller doesn't have to worry about all that prerequisities to be fulfilled and one can simply say:
// Call the function.
WorriedFunction(...);
Now - how should one deal with the following problem?
Like, generally speaking - should this function only do what it is asked for and move the "prerequisity checks" to the caller side:
if (argument1 != null && argument2 + argument3 < 0 && ...) {
// Now all the checks inside can be removed.
NotWorriedFunction();
}
Or - should it simply throw exceptions per every prerequisity mismatch?
if (argument1 != null) throw NullArgumentException;
I'm not sure this problem can be generalized, but still I want to here your thoughts about this - probably there is something I can rethink.
If you have alternative solutions, feel free to tell me about them :)
Thank you.
Every function/method/code block should have a precondition, which are the precise circumstances under which it is designed to work, and a postcondition, the state of the world when the function returns. These help your fellow programmers understand your intentions.
By definition, the code is not expected to work if the precondition is false, and is considered buggy if the postcondition is false.
Whether you write these down in your head, on paper in a design document, in comments, or in actual code checks is sort of a matter of taste.
But a practical issue, long-term, life is easier if you code the precondition and post-condition as explicit checks. If you code such checks, because the code is not expected to work
with a false precondition, or is buggy with a false postcondition, the pre- and post- condition checks should cause the program to report an error in a way that makes it easy to discover the point of failure. What code should NOT do is simply "return" having done nothing, as your example shows, as this implies that it has somehow executed correctly.
(Code may of course be defined to exit having done nothing, but if that's the case, the pre- and post- conditions should reflect this.)
You can obviously write such checks with an if statement (your example comes dangerously close):
if (!precondition) die("Precondition failure in WorriedFunction"); // die never comes back
But often the presence of a pre- or post-condition is indicated in the code by defining a special function/macro/statement... for the language called an assertion, and such special construct typically causes a program abort and backtrace when the assertion is false.
The way the code should have been written is as follows:
void WorriedFunction(...)
{ assert(argument1 != null); // fail/abort if false [I think your example had the test backwards]
assert(argument2 + argument3 >= 0);
assert(!stateManager.currentlyDrawing());
/* body of function goes here */
}
Sophisticated functions may be willing to tell their callers that some condition has failed. That's the real purpose of exceptions. If exceptions are present, technically the postcondition should say something to the effect of "the function may exit with an exception under condition xyz".
That's an interesting question. Check the concept of "Design By Contract", you may find it helpful.
It depends.
I'd like to seperate my answer between case 1, 3 and case 2.
case 1, 3
If you can safely recover from an argument problem, don't throw exceptions. A good example are the TryParse methods - if the input is wrongly formatted, they simply return false. Another example (for the exception) are all LINQ methods - they throw if the source is null or one of the mandatory Func<> are null. However, if they accept a custom IEqualityComparer<T> or IComparer<T>, they don't throw, and simply use the default implementation by EqualityComparer<T>.Default or Comparer<T>.Default. It all depends on the context of usage of the argument and if you can safely recover from it.
case 2
I'd only use this way if the code is in an infrastructure like environment. Recently, I started reimplementing the LINQ stack, and you have to implement a couple of interfaces - those implementations will never be used outside my own classes and methods, so you can make assumptions inside them - the outside will always access them via the interface and can't create them on their own.
If you make that assumption for API methods, your code will throw all sorts of exceptions on wrong input, and the user doesn't have a clue what is happening as he doesn't know the inside of your method.
"Or - should it simply throw exceptions per every prerequisity mismatch?"
Yes.
You should do checks before calling and function and if you own the function, you should make it throw exceptions if arguments passed are not as expected.
In your calling code these exceptions should be handled. Ofcourse arguments passed should be verified before the call.

Which code is more readable?

Suppose I have two methods bool Foo() and bool Bar(). Which of the following is more readable?
if(Foo())
{
SomeProperty = Bar();
}
else
{
SomeProperty = false;
}
or
SomeProperty = Foo() && Bar();
On the one hand, I consider the short-circuiting && to be a useful feature and the second code sample is much shorter. On the other hand, I'm not sure people are generally accustomed to seeing && outside a conditional statement, so I wonder if that would introduce some cognitive dissonance that makes the first sample the better option.
What do you think? Are there other factors that affect the decision? Like, if the && expression is longer than one line that can fit on the screen, should I prefer the former?
Post-answer clarifications:
A few things that I should have included in the initial question that the answers brought up.
Bar() may be more expensive to execute than Foo(), but neither method should have side effects.
The methods are both named more appropriately, not like in this example. Foo() boils down to something like CurrentUserAllowedToDoX() and Bar() is more like, XCanBeDone()
I agree with the general consensus that the Foo() && Bar() form is reasonable unless it is the case that Bar() is useful for its side effects as well as its value.
If it is the case that Bar() is useful for its side effects as well as it's value, my first choice would be to redesign Bar() so that production of its side effects and computation of its value were separate methods.
If for some reason that was impossible, then I would greatly prefer the original version. To me the original version more clearly emphasizes that the call to Bar() is part of a statement that is useful for its side effects. The latter form to me emphasizes that Bar() is useful for its value.
For example, given the choice between
if (NetworkAvailable())
success = LogUserOn();
else
success = false;
and
success = NetworkAvailable() && LogUserOn();
I would take the former; to me, it is too easy to overlook the important side effect in the latter.
However, if it were a choice between
if (NetworkAvailable())
tryWritingToNetworkStorage = UserHasAvailableDiskQuota();
else
tryWritingToNetworkStorage = false;
and
tryWritingToNetworkStorage = NetworkAvailable() && UserHasAvailableDiskQuota();
I'd choose the latter.
I like this shorthand notation assuming your language permits it:
SomeProperty = Foo() ? Bar() : false;
SomeProperty = Foo() && Bar();
This is way more readable. I don't see how anyone could choose the other one frankly. If the && expression is longer then 1 line, split it into 2 lines...
SomeProperty =
Foo() && Bar();
-or-
SomeProperty = Foo() &&
Bar();
That barely hurts readability and understanding IMHO.
It depends on what Foo and Bar do.
For example, IsUserLoggedIn() && IsUserAdmin() would definitely be better as an &&, but there are some other combinations (I can't think of any offhand) where the ifs would be better.
Overall, I would recommend &&.
Neither. I'd start with renaming SomeProperty, Foo and Bar.
What I mean is, you should structure your code as to convey your intentions clearly. With different functions, I might use different forms. As it stands, however, either form is fine. Consider:
IsFather = IsParent() && IsMale();
and
if (FPUAvailable()) {
SomeProperty = LengthyFPUOperation();
} else {
SomeProperty = false;
}
Here, the first form stresses the logical-and relationship. The second one stresses the short-circuit. I would never write the first example in the second form. I would probably prefer the second form for the second example, especially if I was aiming for clarity.
Point is, it's hard to answer this question with SomeProperty and Foo() and Bar(). There are some good, generic answers defending && for the usual cases, but I would never completely rule out the second form.
In what way do you think people might misinterpret the second one? Do you think they'll forget that && shortcircuits, and worry about what will happen if the second condition is called when the first is false? If so, I wouldn't worry about that - they'd be equally confused by:
if (x != null && x.StartsWith("foo"))
which I don't think many people would rewrite as the first form.
Basically, I'd go with the second. With a suitably descriptive variable name (and conditions) it should be absolutely fine.
In the case where the conditional expressions are short and succinct, as is this case, I find the second to be much more readable. It's very clear at a glance what you are trying to do here. The first example though took me 2 passes to understand what was happening.
I would go for the second, but would probably write it like the first time, and then I would change it :)
When I read the first one, it wasn't immediately obvious SomeProperty was a boolean property, nor that Bar() returned a boolean value until you read the else part of the statement.
My personal view is that this approach should be a best practice: Every line of code should be as interpretable as it can with reference to as little other code as possible.
Because statement one requires me to reference the else part of the statement to interpolate that both SomeProperty and Bar() are boolean in nature, I would use the second.
In the second, it is immediately obvious in a single line of code all of the following facts:
SomeProperty is boolean.
Foo() and Bar() both return values that can be interpreted as boolean.
SomeProperty should be set to false unless both Foo() and Bar() are interpreted as true.
The first one, it's much more debuggable
I think, that best way is use SomeProperty = Foo() && Bar(), because it is much shorter. I think that any normal .NET-programmer should know how &&-operator works.
I would choose the long version because it is clear at first glance what it does. In the second version, you have to stop for a few secons until you realize the short-circuit behavior of the && operator. It is clever code, but not readable code.
Wait a minute. These statements aren't even equivalent, are they? I've looked at them several times and they don't evaluate to the same thing.
The shorthand for the first version would be using the ternary operator, not the "and" operator.
SomeProperty = foo() ? bar: false
However, logic error aside, I agree with everyone else that the shorter version is more readable.
Edit - Added
Then again, if I'm wrong and there IS no logic error, then the second is way more readable because it's very obvious what the code is doing.
Edit again - added more:
Now I see it. There's no logic error. However, I think this makes the point that the longer version is clearer for those of us who haven't had our coffee yet.
If, as you indicate, Bar() has side effects, I would prefer the more explicit way. Otherwise some people might not realize that you are intending to take advantage of short circuiting.
If Bar() is self contained then I would go for the more succinct way of expressing the code.
If the first version looked like this:
if (Foo() && Bar())
{
SomeProperty = true;
}
else
{
SomeProperty = false;
}
or like this:
if (Foo())
{
if (Bar())
SomeProperty = true;
else
SomeProperty = false;
}
else
{
SomeProperty = false;
}
Then it would at least be consistent. This way the logic is much harder to follow than the second case.
It is often useful to be able to breakpoint any specific function call individually, and also any specific setting of a variable to a particular value -- so, perhaps controversially, I would be inclined to go for the first option. This stands a greater chance of allowing fine-grained breakpointing across all debuggers (which in the case of C# is not a very large number).
That way, a breakpoint may be set before the call to Foo(), before the call to Bar() (and the set of the variable), and when the variable is set to false -- and obviously the same breakpoints could also be used to trap the Foo() vs !Foo() cases, depending on the question one has in mind.
This is not impossible to do when it is all on one line, but it takes attention that could be used to work out the cause of whatever problem is being investigated.
(C# compiles quickly, so it is usually not a big problem to rearrange the code, but it is a distraction.)
It comes down to being intentional and clear, in my mind.
The first way makes it clear to the casual observer that you aren't executing Bar() unless Foo() returns true. I get that the short circuit logic will keep Bar() from being called in the second example (and I might write it that way myself) but the first way is far more intentional at first glance.
Short-circuiting of AND behavior is not standard in all languages, so I tend to be wary of using it implicitly if that's essential to my code.
I don't trust myself to see the short-circuit immediately after I've switched languages for the fifth time in the day.
So if Boo() should never be called when Foo() returns false, I'd go with version #2, if only as a defensive programming technique.
First method is more readable, but get more lines of codes, second is more EFFECTIVE, no comparision, only one line! I think that second is better
Since you're using c#, I would choose the first version or use the ternary ?: operator. Using && in that manner isn't a common idiom in c#, so you're more likely to be misunderstood. In some other languages (Ruby comes to mind) the && pattern is more popular, and I would say it's appropriate in that context.
I would say code is readable if it is readable to a person with no knowledge of the actual programming language so therefore code like
if(Foo() == true and Bar() == true)
then
SomeProperty = true;
else
SomeProperty = false;
is much more readable than
SomeProperty = Foo() && Bar();
If the programmer taking over the code after you isn't familiar with the latter syntax it will cost him 10 times the time it takes you to write those extra few characters.

Explicit or implicit execution control statement use

I sometimes use
if (this._currentToolForeColor.HasValue)
return this._currentToolForeColor.Value;
else
throw new InvalidOperationException();
other times I use
if (this._currentToolForeColor.HasValue)
return this._currentToolForeColor.Value;
throw new InvalidOperationException();
The two are equivalent, I know, but I am not sure which is the best and why.
This goes even further as you can use other execution-control statements such as brake or continue :
while(something)
{
if(condition)
{
DoThis();
continue;
}
else
break;
}
versus
while(something)
{
if(condition)
{
DoThis();
continue;
}
break;
}
EDIT 1 : Yes the loop example(s) suck because they are synthetic (i.e.: made up for this question) unlike the first which is practical.
Fail early.
Do your validation at the top of the method, and if you get past it, you can use the values in (relative) safety.
public void SomeFunction(object someParameter)
{
if (someParameter == null) throw new ArgumentNullException("someParameter", "Value cannot be null");
// Use the parameter here for stuff
SomeOtherFunction(someParameter, Whichway.Up);
}
The same goes for the return statement. If your method is done, don't wrap stuff in big if statements, just return and get out of there.
See reducing cyclomatic complexity for other examples of this concept. Notice in my example there is only one code path, it's just a matter of how far along you can get with given parameters. Nested ifs and braces (even if you don't use the braces, as in your example) all have a greater impact on readability than the difference between your examples.
First and second options are equivalent to the compiler. But to a human reading the code, the first option is definitely more clear about the intent, and easier to read.
There are limits to what a human reader can absorb from thousands of lines of text designed primarily to function, not to convey meaning. Every tiny effort that makes the task easier is good.
while(something) {
if(condition)
{
DoThis();
continue;
}
else
break; }
Is the same as the following:
while(something && condition)
{
DoThis();
}
To your question: It is always better to be more explicit how the control flows even if it looks redundant (e.g. superfluous else connections are optimized away anyway). So if (cond) return x else throw y is good.
But in case of of error checking for method arguments you should do all checks at the start of the method, so you don't need any else's here.
I guess that depends on your preferences. I personally prefer the first options since it is less verbose. Luckily Resharper and I agree on this, so it is easy to let R# change the code for the shorter version.
I think in this case readibility is the main concern.
If you find yourself scrolling up ad down in the same method, or losing track of execution flow, it should probably be rewritten. break in the above indicates to me that the while condition was not sufficiant check.
It has its uses, but be careful, you dont want some coment appearing from another developer in the team saying
THERE BE DRAGONS HERE!!!
Resharper will recommend that you use this:
if( someCondition )
return foo;
throw new InvalidArgumentException();
But, does that mean that it is therefore better ? I don't know.
Personally, I find the following solution more explicit, and therefore I like it more. But that is just a personal choice.
if( someConditiion )
{
return foo;
}
else
{
throw new ....
}
Regarding your 'while' examples. IMHO, both your code examples suck.
Why not write it like this:
while( something )
{
if( !condition )
break;
DoStuff();
}
For a better and cleaner code, I think it is better to choose always this form:
if(condition)
{
//do stuff
}
else
{
//do stuff
}
..and so on.
It's just a matter of "taste", but even if you have more rows of code, this is clearly readable, because you don't have to interpret nor understand, you can follow the code flow with your finger easily. So, for me, always the else even if a return prevents fallback into following code, always brackets event if you have a one-row if/else and so on.
As far as I can remember, this is also suggested in Framework Design Guidelines, very easy book with lot of "do this" and "don't do this" guidelines.

Is it bad practice to use return inside a void method?

Imagine the following code:
void DoThis()
{
if (!isValid) return;
DoThat();
}
void DoThat() {
Console.WriteLine("DoThat()");
}
Is it OK to use a return inside a void method? Does it have any performance penalty? Or it would be better to write a code like this:
void DoThis()
{
if (isValid)
{
DoThat();
}
}
A return in a void method is not bad, is a common practice to invert if statements to reduce nesting.
And having less nesting on your methods improves code readability and maintainability.
Actually if you have a void method without any return statement, the compiler will always generate a ret instruction at the end of it.
There is another great reason for using guards (as opposed to nested code): If another programmer adds code to your function, they are working in a safer environment.
Consider:
void MyFunc(object obj)
{
if (obj != null)
{
obj.DoSomething();
}
}
versus:
void MyFunc(object obj)
{
if (obj == null)
return;
obj.DoSomething();
}
Now, imagine another programmer adds the line: obj.DoSomethingElse();
void MyFunc(object obj)
{
if (obj != null)
{
obj.DoSomething();
}
obj.DoSomethingElse();
}
void MyFunc(object obj)
{
if (obj == null)
return;
obj.DoSomething();
obj.DoSomethingElse();
}
Obviously this is a simplistic case, but the programmer has added a crash to the program in the first (nested code) instance. In the second example (early-exit with guards), once you get past the guard, your code is safe from unintentional use of a null reference.
Sure, a great programmer doesn't make mistakes like this (often). But prevention is better than cure - we can write the code in a way that eliminates this potential source of errors entirely. Nesting adds complexity, so best practices recommend refactoring code to reduce nesting.
Bad practice??? No way. In fact, it is always better to handle validations by returning from the method at the earliest if validations fail. Else it would result in huge amount of nested ifs & elses. Terminating early improves code readability.
Also check the responses on a similar question: Should I use return/continue statement instead of if-else?
It's not bad practice (for all reasons already stated). However, the more returns you have in a method, the more likely it should be split into smaller logical methods.
The first example is using a guard statement. From Wikipedia:
In computer programming, a guard is a
boolean expression that must evaluate
to true if the program execution is to
continue in the branch in question.
I think having a bunch of guards at the top of a method is a perfectly understandable way to program. It is basically saying "do not execute this method if any of these are true".
So in general it would like this:
void DoThis()
{
if (guard1) return;
if (guard2) return;
...
if (guardN) return;
DoThat();
}
I think that's a lot more readable then:
void DoThis()
{
if (guard1 && guard2 && guard3)
{
DoThat();
}
}
There is no performance penalty, however the second piece of code is more readable and hence easier to maintain.
In this case, your second example is better code, but that has nothing to do with returning from a void function, it's simply because the second code is more direct. But returning from a void function is entirely fine.
It's perfectly okay and no 'performance penalty', but never ever write an 'if' statement without brackets.
Always
if( foo ){
return;
}
It's way more readable; and you'll never accidentally assume that some parts of the code are within that statement when they're not.
I'm going to disagree with all you young whippersnappers on this one.
Using return in the middle of a method, void or otherwise, is very bad practice, for reasons that were articulated quite clearly, nearly forty years ago, by the late Edsger W. Dijkstra, starting in the well-known "GOTO Statement Considered Harmful", and continuing in "Structured Programming", by Dahl, Dijkstra, and Hoare.
The basic rule is that every control structure, and every module, should have exactly one entry and one exit. An explicit return in the middle of the module breaks that rule, and makes it much harder to reason about the state of the program, which in turn makes it much harder to say whether the program is correct or not (which is a much stronger property than "whether it appears to work or not").
"GOTO Statement Considered Harmful" and "Structured Programming" kicked off the "Structured Programming" revolution of the 1970s. Those two pieces are the reasons we have if-then-else, while-do, and other explicit control constructs today, and why GOTO statements in high-level languages are on the Endangered Species list. (My personal opinion is that they need to be on the Extinct Species list.)
It is worth noting that the Message Flow Modulator, the first piece of military software that EVER passed acceptance testing on the first try, with no deviations, waivers, or "yeah, but" verbiage, was written in a language that did not even have a GOTO statement.
It is also worth mentioning that Nicklaus Wirth changed the semantics of the RETURN statement in Oberon-07, the latest version of the Oberon programming language, making it a trailing piece of the declaration of a typed procedure (i.e., function), rather than an executable statement in the body of the function. His explication of the change said that he did it precisely because the previous form WAS a violation of the one-exit principle of Structured Programming.
While using guards, make sure you follow certain guidelines to not confuse readers.
the function does one thing
guards are only introduced as the first logic in the function
the unnested part contains the function's core intent
Example
// guards point you to the core intent
void Remove(RayCastResult rayHit){
if(rayHit== RayCastResult.Empty)
return
;
rayHit.Collider.Parent.Remove();
}
// no guards needed: function split into multiple cases
int WonOrLostMoney(int flaw)=>
flaw==0 ? 100 :
flaw<10 ? 30 :
flaw<20 ? 0 :
-20
;
Throw exception instead of returning nothing when object is null etc.
Your method expects object to be not null and is not the case so you should throw exception and let caller handle that.
But early return is not bad practice otherwise.

Categories