Skip to content

The example showing a function that accepts pipelined and non-pipelined input is incorrect #12228

@fourpastmidnight

Description

@fourpastmidnight

Type of issue

Other (describe below)

Feedback

The following example provided in the documentation is incorrect:

function Get-SumOfNumbers {
    param (
        [int[]]$Numbers
    )

    begin { $retValue = 0 }

    process {
        if ($null -ne $Numbers) {
           foreach ($n in $Numbers) {
               $retValue += $n
           }
        } else {
           $retValue += $_
        }
    }

    end { $retValue }
}

PS> 1, 2, 3, 4 | Get-SumOfNumbers
10
PS> Get-SumOfNumbers 1, 2, 3, 4
10

The condition if ($null -ne $Numbers) always evaluates to $true when numbers are provided, whether they are passed by parameter name or on the command line and results in executing the following foreach block, potentially setting up an additional enumerator to enumerate over a single-element collection. I used the following function to evaluate this very same thing:

function Test-Pipeline {
    Param(
        [Parameter(ValueFromPipeline)]
        [string[]] $Param
    )

    Begin {
        if ($MyInvocation.ExpectingInput) {
            Write-Host "BEGIN: One or more values for -Param were supplied via the pipeline! - $Input"
        } else {
            Write-Host "BEGIN: No values on the pipeline. `$Param: $Param"
        }

        Write-Host "BEGIN: `$Param: $Param"
    }

    Process {
        Write-Host "PROCESS: Still expecting input in process? $($MyInvocation.ExpectingInput)"
        Write-Host "PROCESS: `$Param is not null? $($null -ne $Param)"
        Write-Host "PROCESS: The params are: $Param"
        Write-Host "PROCESS: `$Input is: $Input"
        Write-Host "PROCESS: `$_ is: $_"
    }

    End {
        Write-Host "END: `$Param = $Param"
        Write-Host "END: `$Input is: $Input"
    }
}

Then I executed this function:

PS C:\> Test-Pipeline -Param 'foo', 'bar'
BEGIN: No values on the pipeline. $Param: foo bar
BEGIN: $Param: foo bar
PROCESS: Still expecting input in process? False
PROCESS: $Param is not null? True
PROCESS: The params are: foo bar
PROCESS: $Input is:
PROCESS: $_ is:
END: $Param = foo bar
END: $Input is:

PS C:\> 'foo', 'bar' | Test-Pipeline
BEGIN: One or more values for -Param were supplied via the pipeline! -
BEGIN: $Param:
PROCESS: Still expecting input in process? True
PROCESS: $Param is not null? True
PROCESS: The params are: foo
PROCESS: $Input is: foo
PROCESS: $_ is: foo
PROCESS: Still expecting input in process? True
PROCESS: $Param is not null? True
PROCESS: The params are: bar
PROCESS: $Input is: bar
PROCESS: $_ is: bar
END: $Param = bar
END: $Input is:

As you can see, whether or not the value for $Param was passed by parameter or via the pipeline, inside the Process block, $Param always has a value. When passed via the pipeline, it only contains the current value coming in from the pipeline. Otherwise, it contains all of the values passed to the parameter.

So, the example in the documentation should be fixed as shown below. Also, it would be good for the documentation to mention that one can check for existing pipeline input by inspecting $MyInvocation.ExpectingInput to achieve the desired result:

function Get-SumOfNumbers {
    param (
        [int[]]$Numbers
    )

    begin { $retValue = 0 }

    process {
        if ($MyInvocation.ExpectingInput) {
           $retValue += $_
        } else {
           foreach ($n in $Numbers) {
               $retValue += $n
           }
        }
    }

    end { $retValue }
}

PS> 1, 2, 3, 4 | Get-SumOfNumbers
10
PS> Get-SumOfNumbers 1, 2, 3, 4
10

Page URL

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions?view=powershell-7.5

Content source URL

https://github.com/MicrosoftDocs/PowerShell-Docs/blob/main/reference/7.5/Microsoft.PowerShell.Core/About/about_Functions.md

Author

@sdwheeler

Platform Id

b8594692-1518-3e24-d135-5382996ff646

Document Id

004bf422-04f5-50e2-3c89-2ff449d2867f

Metadata

Metadata

Assignees

Labels

area-aboutArea - About_ topics

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions