Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the value of "switch" type parameter passed to a string parameter?

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?

like image 754
Jim Avatar asked Aug 15 '17 11:08

Jim


1 Answers

@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
like image 138
Ansgar Wiechers Avatar answered Oct 13 '22 11:10

Ansgar Wiechers