问题
The test code (test.ps1):
Param(
[string]$content = $null,
[switch]$flag = $false
)
Write-Host $content
Output:
PS C:\Users\powershell> .\test.ps1 PS C:\Users\powershell> .\test.ps1 -flag $true True PS C:\Users\powershell> .\test.ps1 -flag $false False PS C:\Users\powershell> .\test.ps1 -flag $true -content "lalala" lalala
No matter I set $content to $null, or "", or without any default value, the output is the same.
So why does $content take the value from $flag?
回答1:
@PetSerAl already indicated what your misunderstanding is, but maybe it was a bit too brief, so I'll elaborate a little more.
A [switch] parameter doesn't take a value like regular parameters. You normally set it to true or false respectively by providing or omitting the parameter:
PS C:\> Get-Content .\test.ps1
Param(
[string]$Content = $null,
[switch]$Flag
)
$flag.IsPresent
$Content
PS C:\> .\test.ps1
False
PS C:\> .\test.ps1 -Flag
True
Alternatively you can explicitly pass a value by putting a colon between switch parameter and value:
PS C:\> .\test.ps1 -Flag:$false False PS C:\> .\test.ps1 -Flag:$true True
Whitespace after the colon is allowed, but not before (-Flag: $false passes $false as the switch value, -Flag :$false doesn't).
If you try to assign the switch value without the colon the value is actually passed to the next parameter in line, in your case the -Content parameter:
PS C:\> .\test.ps1 -Flag $false True # value of the parameter $Flag False # value of the (positional) parameter $Content PS C:\> .\test.ps1 -Flag -Content $false True # value of the parameter $Flag False # value of the (named) parameter $Content
If you use -Flag $true (without the colon) and pass a value to the (named) parameter -Content the value $true is passed as an unnamed third parameter (accessible via the automatic variable $args), same as if you put the value at the end of the statement:
PS C:\> Get-Content .\test2.ps1
Param(
[string]$Content = $null,
[switch]$Flag
)
$flag.IsPresent
$Content
$args[0]
PS C:\> .\test2.ps1 -Flag $false -Content 'something'
True
something
False # $false passed as unnamed 3rd parameter
PS C:\> .\test2.ps1 -Flag:$false -Content 'something'
False # $false passed as explicit value of switch parameter $Flag
something
PS C:\> .\test2.ps1 -Flag -Content 'something' $false
True
something
False # $false passed as unnamed 3rd parameter
回答2:
Give this test code a run, calling it as you did in the question. Add this test:
C:\Users\powershell> .\test.ps1 -flag
Script will illustrate the following points:
- As per 4c74356b41's comment, switches are
$falseunless specified on the command line. So-flagsets the$flagswitch to true;-flag $truesets the flag to true and passes the argument$trueto content. - From this, no need to specify
$flag=$falsein script params - Added a test so that you can see when
$contentis empty/null as there is also no need for$content=$null
param(
[string]$content,
[switch]$flag
)
$test = [string]::IsNullOrEmpty($content)
Write-Output "content: $content"
Write-Output "flag : $flag"
Write-Output "Is content null: $test"
回答3:
I will add to this that you can assign the value via splatting as well, changing the value via the splat parameter assignment from $true to $false will alter your switch 'detection'. This is useful when you are using another value or property to determine if a switch should be used or not.
function FooBar {
param (
[switch]
$Foo
)
if ($Foo){
"Foo"
}
else{
"Bar"
}
}
$splat = @{
Foo = $False
}
FooBar @splat
来源:https://stackoverflow.com/questions/45691877/why-is-the-value-of-switch-type-parameter-passed-to-a-string-parameter