0

Since I'm not sure when powershell iterates over $null and when it doesn't, I need to check if the variable is $null or not before each iteration. Maybe someone can explain to me why this is the case and how to handle arrays correctly.

Whenever I iterate over an array and use Where-Object to limit the results to nothing, the result I get is a $null object which cannot be iterated over (correct behavior).

> $array = @(1,2,3) | Where-Object { $false }
> $null -eq $array
True
> $array | ForEach-Object { "begin" } { $null -eq $_ } { "end" }
begin
end

If I initialize the array to $null, it is treated as an iterable value (not quite what you would expect). This behavior seems to result from Powershell interpreting non-arrays as single-entry arrays.

> $array = $null
> $array | ForEach-Object { "begin" } { $null -eq $_ } { "end" }
begin
True
end

The same thing happens when I get the array from a function.

> class MyA { MyA() {} [object]getArray() { return (@(1,2,3) | Where-Object { $false }) }}
> $mya=[MyA]::new()
> $mya.getArray() | ForEach-Object { "begin" } { $null -eq $_ } { "end" }
begin
True
end

The only solution seems to be to pre-check the array for $null each time and replace it with an empty array.

> if ($null -eq $array) { $array = @() }
> $array | ForEach-Object { "begin" } { $null -eq $_ } { "end" }
begin
end

Does anyone have an explanation or another solution to this problem?

voca
  • 1
  • 1
  • "If I initialize the array to $null, it is treated as an iterable value" - it clear _is not_ treated as such - otherwise the `process` block would have run at least once :) – Mathias R. Jessen Nov 11 '22 at 09:58
  • @MathiasR.Jessen If I initialize the array with `$null`, the `process` block will be run through (second example)! There is only one case in which a `$null` array is not iterated (first example)! – voca Nov 11 '22 at 10:05
  • The first example does _not_ produce a `$null` value in `$array`, despite your comparison with `$null` makes it appear so. It is actually `[System.Management.Automation.Internal.AutomationNull]::Value`, see linked duplicate. – zett42 Nov 11 '22 at 11:03
  • @zett42 Thanks, that at least explains why `$null` isn't always the same ;) Unfortunately, all I can do is check for `$null` before each iteration, since there doesn't seem to be a way to return the special null instances in functions! – voca Nov 11 '22 at 11:13
  • @voca I don't understand the use case where you want to return the "special null instances" in functions. If you want to initialize an empty array, then simply do `$array = @()`. If you send this as input into a pipeline, it won't be iterated, as expected. If you want to return "nothing" from a function, then just output nothing or use a `return` statement for early exit, which also returns "nothing". – zett42 Nov 11 '22 at 11:17
  • @zett42 I work a lot with objects and their functions sometimes return an empty subset of the data they hold (like in the example). Now I can choose to check the results for $null in the object function or in the calling script block. – voca Nov 11 '22 at 11:22

0 Answers0