1.5.12 Using Multiple and Early Returns

Overview

A method can contain more than one return statement. An early return ends the current invocation as soon as a special case is found. In Zoo, an Animal should keep its existing Baby when MakePregnant() is called again.

public void MakePregnant()
{
    if (this.GetIsPregnant())
    {
        return;
    }

    this.Baby = new Animal();
    // Set the new Baby's fields here.
}

GetIsPregnant() returns true when Baby already references an Animal. Then return; ends the void method; the Baby creation code is skipped. If the result is false, execution passes the guard and creates the Baby. The return does not delete or replace the existing object.

Compare an Early Exit with a Value Return
A void method may use return; without an expression. A value-returning method can also return early, but it must provide a value of its declared type, such as return false; in a bool method. Any statements after the selected return are unreachable du
Compare an Early Exit with a Value Return
  • New
  • Changed
  • Removed

A void method may use return; without an expression. A value-returning method can return from more than one location, but each reached return must provide a value of its declared type:

public bool CanCreateBaby()
{
    if (this.GetIsPregnant())
    {
        return false;
    }

    return this.Sex == "Female";
}

The first return handles an existing Baby. Otherwise the second return answers whether this Animal is female. No statement after the chosen return executes during that call.

Trace the Outcome

Call MakePregnant() first with a null Baby and then with an existing Baby. Identify which route reaches the creation statement. For a value-returning method, check the value returned by each early path as well as the normal path.

A return is reached only after its guard has been evaluated. In CanCreateBaby(), a pregnant animal never checks Sex because the first branch returns false. For an animal without a Baby, the second return evaluates Sex. Changing the order would still compile but could change which checks execute, so trace the guards in source order.