Is a string parameter sent to PowerShell not really a string?
I am bit confused of the beh开发者_如何学编程aviour of the script below:
Test.ps1:
param(
[array]$Value = $(throw "Give me a value")
)
Write-Host $Value
$Value | Get-Member -MemberType Method
$Value.ToUpper()
Running the script:
PS C:\Temp> .\weird.ps1 test
TypeName: System.String
Name MemberType Definition
—- ———- ———-
…
ToUpper Method string ToUpper(), string ToUpper(System.Globalization.CultureInfo culture)
…
Method invocation failed because [System.Object[]] doesn’t contain a method named ‘ToUpper’.
At C:\Temp\weird.ps1:6 char:15
+ $Value.ToUpper <<<< ()
+ CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Why do I get a MethodNotFound exception? Get-Member clearly says it is a string.
What's happening here is that the variable $value
is typed to Object[]
in the script. The call to Get-Member
works because you are piping the value into the function. Hence instead of seeing the array it sees the values in the array which are indeed typed to String
. This can be viewed by using the following Get-Member
call without piping
Get-Member -MemberType Method -InputObject $value
This is also why ToUpper correctly fails (it's an array not a String
).
When you pipe a collection of anything in powershell, it gets "unrolled" and sent one by one to the right hand side of the bar (pipe) character. This means that the contents of the array get sent to get-member. Get-member only accepts the first item sent to it, so it shows you the members of the string. Your parameter is of type [array]
, so the parameter binder sets $value to an array of length 1, containing your string "test."
Example:
ps> @(1,"hello",3) | gm
... shows members of int32
ps> @("hello", 1, 3) | gm
... shows members of string
In order to see the members of an array when you pipe it, you should wrap it in another array, so it becomes the unrolled item:
ps> ,@("hello", 1, 3) | gm
... shows members of array
The leading comma "," creates a wrapping array.
-Oisin
$Value is actually an array, because that is how you declare the parameter in your param block.
精彩评论