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