4

I thought if this was possible it might work using parameter sets so I tried the following:

Function New-TestMultipleDefaultValues {
    [CmdletBinding(DefaultParameterSetName="Default1")]
    param (
        [Parameter(Mandatory,ParameterSetName="Default1")]$SomeOtherThingThatIfSpecifiedShouldResultInTest1HavingValue1,
        [Parameter(ParameterSetName="Default1")]$Test1 = "Value1",
        [Parameter(ParameterSetName="Default2")]$Test1 = "Value2"
    )
    $PSBoundParameters
}

Executing this to create the function results in the error Duplicate parameter $test1 in parameter list. so it doesn't look like this way is an option.

The only thing I can think of at this point is to do something like this:

Function New-TestMultipleDefaultValues {
    param (
        $SomeOtherThingThatIfSpecifiedShouldResultInTest1HavingValue1,
        $Test1
    )
    if (-not $Test1 -and $SomeOtherThingThatIfSpecifiedShouldResultInTest1HavingValue1) {
        $Test1 = "Value1"
    } elseif (-not $Test1 -and -not $SomeOtherThingThatIfSpecifiedShouldResultInTest1HavingValue1) {
        $Test1 = "Value2"
    }

    $Test1
}

Which works but seems ugly:

PS C:\Users\user> New-TestMultipleDefaultValues -SomeOtherThingThatIfSpecifiedShouldResultInTest1HavingValue1 "thing"
Value1
PS C:\Users\user> New-TestMultipleDefaultValues
Value2
PS C:\Users\user> New-TestMultipleDefaultValues -Test1 "test"
test

Any better way to accomplish this?

2 Answers 2

8

The following should work:

Since there is then no longer a need for explicit parameter sets, I've omitted them; without specific properties, the [Parameter()] attributes aren't strictly needed anymore either.

Function New-TestMultipleDefaultValues {

  [CmdletBinding()]
  param (
    [Parameter()] $SomeOtherThing,
    [Parameter()] $Test1 = 
      ('Value2', 'Value1')[$PSBoundParameters.ContainsKey('SomeOtherThing')]
  )
    
  # * As expected, if -Test1 <value> is explicitly specified, 
  #   parameter variable $Test1 receives that value.
  # * If -Test1 is omitted, the expression assigns 'Value1` to $Test1
  #   if -SomeOtherThing was specified, and 'Value2' otherwise.
  $Test1 # Output the effective value of $Test1

}
  • It is possible to use expressions as parameter default values.

    • The above code is an expression and therefore can be used as-is.
    • To use a single command (a call to a PowerShell cmdlet, function, script or to an external program) as an expression, enclose it in (...), the grouping operator.
    • In all other cases you need $(...), the subexpression operator (or @(...), the array-subexpression operator) to convert the code to an expression; these cases are:
      • A Throw statement (and, hypothetically, exit and return statements, but you wouldn't use them in this context)
      • A compound construct such as foreach, while, ...
      • Multiple commands, expressions, or compound constructs, separated with ;
  • However, it is safe to always use $(...) (or @(...)) to enclose the code that calculates the default value, which you may opt to do for simplicity.

  • These expressions are evaluated after the explicitly specified parameters have been bound, which allows an expression to examine what parameters have been bound, via the automatic $PSBoundParameters variable:

    • ('Value2', 'Value1')[$PSBoundParameters.ContainsKey('SomeOtherThing')] is simply a more concise reformulation of
      if ($PSBoundParameters.ContainsKey('SomeOtherThing')) { 'Value1' } else { 'Value2' }
      that takes advantage of [bool] values mapping onto 0 ($false) and 1 ($true) when used as an array index (integer).

    • In PowerShell v7+ you could use a ternary conditional instead, which has the added advantage of short-circuiting the evaluation: $PSBoundParameters.ContainsKey('SomeOtherThing') ? 'Value1' : 'Value2'

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Surrounding the conditional default value with $ outside parentheses is got me what I wanted.
Glad to hear it, @SubjectiveReality; I've since realized that $(...) is often not needed: expressions can be used as-is, single commands can be enclosed in (...). However, given that these distinctions may not be obvious, categorically using $(...) is an option - please see my update.
0

You may want to look at dynamic parameters. You declare a section called dynamicparams {} and inside you can create parameters on the fly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.