TessellatingHeckler
TessellatingHeckler

Reputation: 29003

PowerShell - why does looking up an array in a Hashtable return an empty array?

I hit this while looking for something else, so there is no wider code or purpose beyond puzzling over this example:

$H = @{}                 # new, empty hashtable

                         # String test - lookup fails, hashtable returns $null
$H["test"].GetType()     # "You cannot call a method on a null-valued expression."


                         # Array test - should do the same
$Key = @('a','b')              
$H[$Key].GetType()       # Object[]  what?? Where did this come from? <--<<====<<====<<
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


                         # Double check that ..
$H.ContainsKey($Key)     # False. Doesn't contain the key(!)

$H.Values.Count          # 0. It's empty. As it should be. 

How (why) does a lookup on an empty hashtable return an object[] when the key is an array, but not otherwise?

NB. I'm aware that you can't/shouldn't use an array as a hashtable key at least partly because arrays are not equal unless they are the same object in memory e.g. array/object keys for hashtables in powershell; but arrays do have .GetHashCode() - shouldn't it still return $null for a failed lookup no matter what they key is?

Happens on Windows/PSv4 and Linux/PS6-alpha

Here is the CoreCLR Hashtable source for this[Object key] although I can't make anything relevant of that. Maybe this is in the higher level PowerShell hashtable handling (which I haven't found yet).

Upvotes: 1

Views: 844

Answers (1)

user4003407
user4003407

Reputation: 22122

This is PowerShell feature which allows you to specify array of indexes when indexing a collection:

$Array = 10..1
$Indexes = 1, 3, 5
$Array[$Indexes] # 9, 7, 5

$Hash = @{
    a = 1
    b = 2
    c = 3
}
$Indexes = 'c', 'f', 'a'
$Hash[$Indexes] # 3, $null, 1
                # System.Collections.Hashtable designed to return null,
                # when asking not existing key.

$String = 'abcdefghijklmnopqrstuvwxyz'
$Indexes = 7, 4, 11, 11, 14
$String[$Indexes] # h, e, l, l, o

If you really want to index hashtable by array as single object, then you can use Item parameterized property:

$Array = 1..10
$Hash = @{ $Array = 'Value' }
$Hash.Item($Array)

Upvotes: 3

Related Questions