Default value of parameter is not used in function

后端 未结 4 1188
孤城傲影
孤城傲影 2021-01-01 07:46

I have a very basic PowerShell script:

Param(
    [string]$MyWord
)

function myfunc([string] $MyWord) {
    Write-Host \"$MyWord\"
}
myfunc @PSBoundParamete         


        
相关标签:
4条回答
  • 2021-01-01 08:23

    Very simple way is,

    function myfunc([string]$MyWord = "hi") {
    Write-Output $MyWord
    }
    
    0 讨论(0)
  • 2021-01-01 08:34

    A parameter is bound only if you actually pass it a value, meaning that a parameter's default value does not show up in $PSBoundParameters. If you want to pass script parameters into a function, you must replicate the script parameter set in the function parameter set:

    Param(
        [string]$MyWord = 'hi'
    )
    
    function myfunc([string]$MyWord = 'hi') {
        Write-Host "$MyWord" 
    }
    
    myfunc @PSBoundParameters

    Maintaining something like this is easier if you define both parameter sets the same way, though, so I'd put the function parameter definition in a Param() block as well:

    Param(
        [string]$MyWord = 'hi'
    )
    
    function myfunc {
        Param(
            [string]$MyWord = 'hi'
        )
    
        Write-Host "$MyWord" 
    }
    0 讨论(0)
  • 2021-01-01 08:36

    Automatic variable $PSBoundParameters, as the name suggests, contains only bound parameters, where bound means that an actual value was supplied by the caller.

    Therefore, a parameter default value does not qualify as binding the associated parameter, so $MyWord with its default value of 'hi' does not become part of $PSBoundParameters.

    Note: Arguably, a parameter with a default value should also be considered bound (it is bound by its default value, as opposed to by a caller-supplied value). Either way, it would be convenient to have an automatic variable that includes default values too, so as to enable simple and comprehensive passing through of arguments. A suggestion has been submitted to the PowerShell GitHub repository here.


    Workarounds

    • The following solutions assume that you want to pass the default value through, and don't want to simply duplicate the default value in function myfunc (as demonstrated in Ansgar Wiecher's helpful answer), because that creates a maintenance burden.

    • Regarding function syntax: The following two forms are equivalent, though you may prefer the latter for consistency and readability.

      • function myfunc([string] $MyWord = 'hi') { ... }
        parameter declaration inside (...) after the function name.
      • function myfunc { param([string] $MyWord = 'hi') ... }
        parameter declaration inside a param(...) block inside the function body.

    A simple fix would be to add the default value explicitly to $PSBoundParameters:

    Param(
         [string]$MyWord = 'hi'
    )
    
    function myfunc ([string] $MyWord){
        Write-Host "$MyWord" 
    }
    
    # Add the $MyWord default value to PSBoundParameters.
    # If $MyWord was actually bound, this is effectively a no-op.
    $PSBoundParameters.MyWord = $MyWord
    
    myfunc @PSBoundParameters
    

    To achieve what you want generically, you must use reflection (introspection):

    Param(
         [alias('foop')]
         [string]$MyWord = 'hi'
    )
    
    function myfunc ([string] $MyWord){
        Write-Host "$MyWord" 
    }
    
    # Add all unbound parameters that have default values.
    $boundAndDefaultValueParams = $PSBoundParameters
    foreach($paramName in $MyInvocation.MyCommand.Parameters.Keys) {
      if (-not $boundAndDefaultValueParams.ContainsKey($paramName)) {
        $val = Get-Variable $paramName -ValueOnly
        if ($null -ne $val) { $boundAndDefaultValueParams.Add($paramName, $val) }
      }
    }
    
    myfunc @boundAndDefaultValueParams
    
    0 讨论(0)
  • 2021-01-01 08:39

    If you want to use "Param" enclose it in the function like this:

    function myfunc {
    
        Param(
            [string]$MyWord='hi'
        )
    
        Write-Host "$MyWord" 
    }
    
    0 讨论(0)
提交回复
热议问题