I am currently using anonymous functions in Powershell and I noticed there is a weird casting problem when going from System.ValueType to System.Object.
Take the following example:
$f = {
param($InputArray)
Write-Host "`$Arr Type During Call:" ($InputArray.GetType().FullName)
Write-Host "`$Arr Contents During Call:" $InputArray
}
[object[]]$Arr = [object[]]@($true, $false)
Write-Host "`$Arr Type Before Call:" ($Arr.GetType().FullName)
Write-Host "`$Arr Contents Before Call:" $Arr "`n"
$f.Invoke($Arr)
The following example will output the following:
$Arr Type Before Call: System.Object[]
$Arr Contents Before Call: True False$Arr Type During Call: System.Boolean
$Arr Contents During Call: True
It looks like Powershell casted my variable $Arr into the type System.Boolean. If I force the parameter to be of type object[], a new problem is introduced:
$f = {
param([object[]]$InputArray)
Write-Host "`$Arr Type During Call:" ($InputArray.GetType().FullName)
Write-Host "`$Arr Contents During Call:" $InputArray
}
[object[]]$Arr = [object[]]@($true, $false)
Write-Host "`$Arr Type Before Call:" ($Arr.GetType().FullName)
Write-Host "`$Arr Contents Before Call:" $Arr "`n"
$f.Invoke($Arr)
The new change produces the following output:
$Arr Type Before Call: System.Object[]
$Arr Contents Before Call: True False$Arr Type During Call: System.Object[]
$Arr Contents During Call: True
Powershell is only providing the anonymous function one element of my array. What is going on here?
boolean when I clearly am giving it an object array? Use:
$f.Invoke((, $Arr))
or, more PowerShell-idiomatically:
& $f $Arr
As for what you tried:
$f.Invoke($Arr)
passes the elements of array $Arr as individual arguments.
Since your script block $f defines only one parameter, only the first element of $Arr is bound to that parameter, $InputArray.
(, ($Arr)) works around that problem by wrapping the array in an auxiliary single-element array, which $f.Invoke() then unwraps and therefore passes $Arr as a single argument.
That said, using object methods in PowerShell is generally an awkward experience, given that the invocation syntax causes confusion with PowerShell's command syntax.
Often, it's possible to stay in the realm of PowerShell's commands and operators.
Specifically, the PowerShell-idiomatic way to invoke script blocks ({ ... }) is to use &, the call operator (to execute the script block in a child scope; alternatively ., the dot-sourcing operator, (typically) executes directly in the caller's scope).
& (and .) use command syntax (argument parsing mode), where arguments are passed without parentheses and separated with whitespace rather than , - see this answer for more information.
Therefore, & $f $Arr interprets $Arr as the 1st and only argument to be passed as a whole to the script block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With