I'm experimenting with True and False in Powershell 4.0. Here are the results when looking at an empty array and an empty hash table:
PS C:\Users\simon> $a = @()
PS C:\Users\simon> if ($a) { Write-Host "True" } else { Write-Host "False" }
False
PS C:\Users\simon> $a = @{}
PS C:\Users\simon> if ($a) { Write-Host "True" } else { Write-Host "False" }
True
Why do empty hash tables evaluate to True when empty arrays evaluate to False?
According to the Powershell documentation About Comparison Operators:
When the input is a collection of values, the comparison operators return any matching values. If there are no matches in a collection, comparison operators do not return anything.
From that I would expect both a hash table and an array to act the same when they are empty, since both are collections. I would expect both to evaluate to False because they return nothing to the if
clause.
An array, which is sometimes referred to as a collection, stores a list of items. A hash table, which is sometimes called a dictionary or an associative array, stores a paired list of items.
An empty PowerShell hash table is created using @{}. PowerShell hash table values are added using $table. Add(key, value) syntax or $table. key = value syntax.
This isn't a question of True/False. You can test this using the Boolean operators $true
and $false
. I've used $h
as the empty hashtable @{}
PS C:\> $a = @()
PS C:\> $h = @{}
PS C:\> if ($a -eq $true) { Write-Host "True" } else { Write-Host "False" }
False
if ($h -eq $true) > False
if ($a -eq $false) > False
if ($h -eq $false) > False
Also not equal to automatic variable $null
:
if($a -eq $null) > False
if($h -eq $null) > False
As per iRon's link, Count
is a better test to see if a hashtable/array is empty. Related Length
The different behaviour will be related to the fundamental types.
PS C:\> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS C:\> $h.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
It's to do with how the if
statement works and the Length
property, AFAICS. Below is my (admittedly shaky) understanding from multiple StackOverflow posts and external links.
Get-Member
behaviour is different - see Mathias's explanation
$a | Get-Member # Error - Get-Member : You must specify an object for the Get-Member cmdlet.
$h | Get-Member # TypeName: System.Collections.Hashtable. Has Count method, no Length property
Get-Member -InputObject $a # TypeName: System.Object[]. Has Count method, has Length property
The Length
property of the variables is different. But the hashtable does not have a Length
property - see mjolinar's answer.
$a.Length > 0
$h.length > 1
Combining with Ansgar's link explains the different behaviors in the if
statement as it seems to be implicitly getting the Length
property . It also allows us to do this:
if ($a.Length -eq $true) > False
if ($h.Length -eq $true) > True
Using the IsNullOrEmpty method of the [String] .Net class gives different output compared to $null
, I assume because this also relies on the Length
.
if ([string]::IsNullOrEmpty($a)) > True
if ([string]::IsNullOrEmpty($h)) > False
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