Some background: When an empty pipeline is assigned to a variable, the value is [System.Management.Automation.Internal.AutomationNull]::Value
as explained here https://stackoverflow.com/a/22365076/37572
AutomationNull has some interesting properties
- AutomationNull -eq $null
- AutomationNull -is [psobject]
- if AutomationNull is passed to function($x), then the $x argument value is a simple $null
The code below assigns AutomationNull to an array member and then calls function f($x) with the array as the argument. The surprising result is that the array member that used to contain AutomationNull now contains a simple $null.
"PSVersion "+ $PSVersionTable.PSVersion
Write-Host -ForegroundColor Yellow "******** array initialized"
$array = @(0,$null,2)
for($i=0; $i -lt $array.Count; $i++) {
if ($null -eq $array[$i]) {
if ($array[$i] -is [psobject]) {"array[$i] is null and [psobject]"
} else {"array[$i] is null"}
} else {"array[$i] is " + $array[$i]}
}
Write-Host -ForegroundColor Yellow "******** array[1] set to empty pipeline"
$emptypipe = (@()|%{1})
$array[1] = $emptypipe
for($i=0; $i -lt $array.Count; $i++) {
if ($null -eq $array[$i]) {
if ($array[$i] -is [psobject]) {"array[$i] is null and [psobject]"
} else {"array[$i] is null"}
} else {"array[$i] is " + $array[$i]}
}
function f($x) {Write-Host -ForegroundColor Yellow '******** called: f -x $array'}
f -x $array
for($i=0; $i -lt $array.Count; $i++) {
if ($null -eq $array[$i]) {
if ($array[$i] -is [psobject]) {"array[$i] is null and [psobject]"
} else {"array[$i] is null"}
} else {"array[$i] is " + $array[$i]}
}
Results:
PSVersion 3.0
******** array initialized
array[0] is 0
array[1] is null
array[2] is 2
******** array[1] set to empty pipeline
array[0] is 0
array[1] is null and [psobject]
array[2] is 2
******** called: f -x $array
array[0] is 0
array[1] is null
array[2] is 2
So it seems that simply calling f($x) with the array as the argument has changed the contents of the array.
In itself I agree that it is a weird edge case, but it seems to be an example of a pretty basic assumption being broken by the language.
Can anyone explain this behaviour?
P.S. Sorry that the above code has to repeat the for loop verbatim three times, but turning it into a function hides the actual test result.