A non-void method may have several possible return statements when different execution paths produce different results.
For example:
public string GetGoalCategory(int goals)
{
if (goals >= 3)
{
return "High scoring";
}
if (goals == 2)
{
return "Two goals";
}
return "Fewer than two";
}Only one return statement executes during one method call.
When execution reaches:
return "High scoring";the method sends that value back to its caller and stops executing.
Statements later in the method are not reached during that call.
This makes a return an execution-flow boundary.
Suppose:
goals = 4The first condition:
goals >= 3is true.
The method executes:
return "High scoring";and finishes immediately.
The later condition:
goals == 2is not evaluated.
Suppose:
goals = 2The first condition is false.
Execution continues.
The second condition is true.
The method executes:
return "Two goals";and finishes.
The final return is not reached.
For:
goals = 1both earlier conditions are false.
Execution reaches:
return "Fewer than two";This final return supplies the result for all remaining values.
An early return occurs before the normal end of the method.
Suppose:
public string GetTeamName()
{
if (this.team == null)
{
return "No team";
}
return this.team.name;
}The null case is handled immediately.
If the Team reference is null, the method returns:
"No team"and stops.
Only when the reference exists does execution continue to:
return this.team.name;A guard-style early return answers:
For the Team example:
team is null?
├─ yes → return "No team"
└─ no → continue and use teamThis can make the method's flow straightforward.
Having several return statements does not automatically mean every path returns.
You still need to trace every possible execution path.
For example:
public int GetScore(int goals)
{
if (goals > 0)
{
return goals;
}
}The positive path returns.
The zero-or-lower path does not.
The method still has an incomplete path.
For:
public string GetGoalCategory(int goals)every return must produce a string-compatible value.
The method cannot return an integer in one branch merely because that value is convenient.
The method contract applies to every return statement.
A single method call returns one result.
A method with three return statements does not send three values back.
It has three possible places where execution may finish.
Only the return reached by the selected path executes.
Do not add early returns simply because they are allowed.
Use them when the method's logic becomes clearer.
A good early return often handles a condition that makes the normal remainder of the method unnecessary.
public string GetAvailabilityText()
{
if (this.isAvailable)
{
return "Available";
}
else
{
return "Unavailable";
}
}public string GetAvailabilityText()
{
if (this.isAvailable)
{
return "Available";
}
return "Unavailable";
}Both can produce the same result.
The important requirement is that the logic is correct and every path returns the promised type.
When reading multiple returns:
Multiple returns are easiest to understand when you trace one complete path at a time.