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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.