1

If I use .Count to check the number of items in an empty array, like this:

$theNames = @()
$theTotalNames = $theNames.Count

it finds nothing, and the numeric variable $theTotalNames is 0, as expected

But I have a situation where if I use .Count to check the contents of seemingly empty array, it is returning 1.

I'm populating the array with the results returned from the Invoke-RestMethod query like this:

$responseData = Invoke-RestMethod -Uri $url -Method Get -Headers $headers
$theNames = @($responseData.PsObject.Properties["the_field"].value.field_name)
$theTotalNames = $theNames.Count

If the query returns nothing because there were no fields found, $theTotalNames somehow equals 1. If the query returns one or more items, $theTotalItems will correctly equal 1.. or higher

When I display the contents of $theNames array after the query that returned nothing, the array seems empty.

If I check what's in the array, like this:

 if ($theNames) {
     "The array contains something"
 }
 else {
     "The array contains nothing"
 }

the console always says the array contains nothing.

So, why does .Count think there's at lease one item in the array?

2
  • 1
    Show result of: $null -eq $theNames[0] Commented Mar 2, 2018 at 0:17
  • $null is returning True Commented Mar 2, 2018 at 0:37

2 Answers 2

2

As PetSerAl implies in a comment, the array may not be empty but may have a single element that happens to be $null; the .Count property reports the number of elements irrespective of the value of the elements:

@($null).Count # -> 1

Work around the problem as follows (assuming actual values are never the empty string):

$theTotalNames = if ($theNames) { $theNames.Count } else { 0 }

This relies on the fact that a single-element array that contains a "falsy" value is regarded as $False in a Boolean context.


Optional background information

In PowerShell, $null is generally a "something" (the "null scalar"), whereas there is also a "null collection", which is closer to "nothing", namely the [System.Management.Automation.Internal.AutomationNull]::Value singleton, which is "returned" by commands that have no output at all.

The simplest way to produce it is to call an empty script block: & {}

Trying to wrap that in an array indeed yields an empty array:

@(& {}).Count  # -> 0

However, in PSv3+ there is (at least?) one context in which $null too is considered "nothing":

foreach ($el in $null) { "loop entered" }  # loop is NOT entered.

I presume that the rationale for this intentional inconsistency is that uninitialized variables default to $null and that entering the loop for uninitialized variables would be undesirable.
For more, see this GitHub discussion.

Sign up to request clarification or add additional context in comments.

2 Comments

IMHO, it is not that historical. IIRC, before v3 foreach count $null as value and enter the loop.
@PetSerAl: You are correct, thanks. The behavior was introduced in v3. I've updated the answer and added a - speculative - rationale for this behavior. Do let us know if you know more about this. Similarly, tell us if you know of other scenarios where $null is "nothing".
0

In my instance, I had already defined the $array variable, so mklement0's answer (checking the value of if $array) wouldn't have worked as the variable is always defined, just not always populated, despite what .count says.

I worked around it in the end by doing this:

if (($array | select -first 1) -eq $null) {
    write-host "Array is empty"
}

In short, we get the first result from the array and see whether it is $null. In my case this works because we never expect any of the elements in the array to be $null.

If you are in a situation where array elements can be $null, one option you might have is to remove these entries beforehand using where-object, like so; you could then perform the original .count check as all zero entries will have been removed.

$array2=$array | ? {$_ -ne $null}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.