Reputation: 5949
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?
Upvotes: 4
Views: 2392
Reputation: 437100
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 grouping operator.$(...)
, the subexpression operator (or @(...)
, the array-subexpression operator) to convert the code to an expression; these cases are:
Throw
statement (and, hypothetically, exit
and return
statements, but you wouldn't use them in this context)foreach
, while
, ...;
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'
Upvotes: 8
Reputation: 77
You may want to look at dynamic parameters. You declare a section called dynamicparams {} and inside you can create parameters on the fly.
Upvotes: 0