The PowerShell return keyword

The return keyword is probably the most over used keyword in PowerShell that’s used in unnecessary scenarios. You’ll often find it used to simply return the output of a function:

function New-MrGuid {
    $Guid = [System.Guid]::NewGuid()
    Return $Guid
}

return1a.jpg

In that scenario, using the return keyword is totally unnecessary. If you do want to return the value of the variable, simply let PowerShell take care of returning the output:

function New-MrGuid {
    $Guid = [System.Guid]::NewGuid()
    $Guid
}

I received a comment on Twitter from Bill Hurt about using the Write-Output cmdlet in this scenario and although I didn’t specify it in the previous example, I typically do use Write-Output instead of just specifying the variable itself:

function New-MrGuid {
    $Guid = [System.Guid]::NewGuid()
    Write-Output $Guid
}

return1a.jpg

In the previous example, there’s no reason to store the value in a variable, simply create the new GUID and let PowerShell handle returning the output all in one command:

function New-MrGuid {
    [System.Guid]::NewGuid()
}

return1a.jpg

The return keyword does have a valid use case though. The following function does not use the return keyword:

function Test-Return {
    [CmdletBinding()]
    param (
        [int[]]$Number
    )

    foreach ($N in $Number) {
        if ($N -ge 4) {
            $N
        }
    }
}

Without the return keyword any number greater than or equal to four is returned:

Test-Return -Number 3, 5, 7, 9

return2a.jpg

Notice that the return keyword has been added to the function without any other changes:

function Test-Return {
    [CmdletBinding()]
    param (
        [int[]]$Number
    )

    foreach ($N in $Number) {
        if ($N -ge 4) {
            Return $N
        }
    }
}

With the return keyword, the first value that is greater than or equal to 4 will be returned and then the foreach loop will exit without testing the numbers 7 or 9.

Test-Return -Number 3, 5, 7, 9

return3a.jpg

Not only does it exit the foreach loop, but the entire function so if additional code existed after the foreach loop, it wouldn’t be executed either. A slightly modified version of the previous function will be used to demonstrate this.

For the first test, the return keyword is omitted:

function Test-Return {
    [CmdletBinding()]
    param (
        [int[]]$Number
    )

    $i = 0

    foreach ($N in $Number) {
        if ($N -ge 4) {
            $i++
            $N
        }
    }

    Write-Verbose -Message "A total of $i items were returned."
}

The verbose output after the foreach loop is included in the output when specifying the verbose parameter:

return4a.jpg

The return keyword has been added to the following function:

function Test-Return {
    [CmdletBinding()]
    param (
        [int[]]$Number
    )

    $i = 0

    foreach ($N in $Number) {
        if ($N -ge 4) {
            $i++
            Return $N
        }
    }

    Write-Verbose -Message "A total of $i items were returned."
}

Notice that although the verbose parameter was specified, the verbose output is not included because the return keyword causes the function to exit before it gets to that point:

return5a.jpg

Of course, if the portion of the code with the return keyword isn’t run, the verbose output will be included in the output when the verbose parameter is specified:

return6a.jpg

As Jaap Brasser noted via a comment to this post, it’s worth noting that the return keyword is actually required when working with classes in PowerShell version 5 so that’s another valid use case for it. I’ll plan to cover classes in a future blog article.

For more information about the return keyword, see the about_Return help topic.

µ