Search code examples
powershellvariableshashtable

How do you check if a PowerShell variable is an ordered hashtable?


In PowerShell, how do you check if a variable is a hashtable, whether it be ordered or not?

In the first instance, I was testing if an ordered hashtable was of type Hashtable, but it seems that it is not.

Following this, I checked the variable type using GetType(). This seems to show that ordered hashtables are of type OrderedDictionary.

Finally, I tested if an ordered hashtable was of type OrderedDictionary, but this results in an error.

I assume that there must be a way to do this?

Checking for Hashtable only

$standard = @{}
$ordered = [ordered]@{}

if ($standard -is [Hashtable]) { Write-Output "True" } else { Write-Output "False" }
if ($ordered -is [Hashtable]) { Write-Output "True" } else { Write-Output "False" }

True
False

Getting the type of variable for normal and ordered hashtables

Looking at the type of the variables, I can see that $ordered seems to be a different type called OrderedDictionary.

$standard = @{}
$ordered = [ordered]@{}

Write-Output $standard.GetType()
Write-Output $ordered.GetType()



IsPublic IsSerial Name              BaseType  
-------- -------- ----              --------  
True     True     Hashtable         System.Object  
True     True     OrderedDictionary System.Object

Checking for Hashtable or OrderedDictionary

However, when I check if a variable is of type OrderedDictionary, I'm presented with an error stating that the type cannot be found.

$standard = @{}
$ordered = [ordered]@{}

if (($standard -is [Hashtable]) -or ($standard -is [OrderedDictionary])) { Write-Output "True" } else { Write-Output "False" }
if (($ordered -is [Hashtable]) -or ($ordered -is [OrderedDictionary])) { Write-Output "True" } else { Write-Output "False" }

True
Unable to find type [OrderedDictionary].


Solution

  • As has been point out in the comments, the full namespace-qualified type name is:

    [System.Collections.Specialized.OrderedDictionary]
    

    If you want to accept both types, as a parameter argument in a function for example, use their common interface IDictionary:

    function Test-IsOrdered
    {
      param(
        [System.Collections.IDictionary]
        $Dictionary
      )
    
      $Dictionary -is [System.Collections.Specialized.OrderedDictionary]
    }
    

    Test-IsOrdered will now accept any dictionary type including a regular [hashtable]: Test-IsOrdered @{}, but only Test-IsOrdered ([ordered]@{}) will return $true