The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

StephenD (3) [Avatar] Offline
#1
Hello again,

I was playing around with variable assignment to an array, and I noticed something weird.

I have opened a new PS console, and (I thought) I defined an array:

PS C:MyScripts> $a = @{ONE = "One"; TWO = "Two"}
PS C:MyScripts> $a.gettype()

IsPublic.....IsSerial.....Name...............BaseType
--------........--------........------..................--------
True..........True......... Hashtable........ System.Object
................................ ^^^^^^^^^^^
.................................PS types this as a hashtable

I do the same thing for the second element in the desired array:


PS C:MyScripts> $b = @{ONE = "OneOne"; TWO = "TwoTwo"}
PS C:MyScripts> $b.gettype()

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

Once again it is defined as a Hashtable, so I cast both variables as [array] and I can combine them in an array:

PS C:MyScripts> [array]$a = @{ONE = "One"; TWO = "Two"}
PS C:MyScripts> [array]$b = @{ONE = "OneOne"; TWO = "TwoTwo"}
PS C:MyScripts> $c
PS C:MyScripts> $c = $a + $b
PS C:MyScripts> $c.gettype()

IsPublic.....IsSerial.....Name...............BaseType
--------........--------........------..................--------
True.........True..........Object[].............System.Array

Now when I define $a again, it's default type is [array]

PS C:MyScripts> $a = @{ONE = "One"; TWO = "Two"}
PS C:MyScripts> $a.gettype()

IsPublic.....IsSerial.....Name...............BaseType
--------........--------........------..................--------
True.........True..........Object[].............System.Array
If I create a new variable with the same construct, it is initialized as type [Hashtable]

PS C:MyScripts> $g = @{ONE = "One"; TWO = "Two"}
PS C:MyScripts> $g.gettype()

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

After casting $g as [Array], any new invocation of this variable with that construct will create a type [Array]
If I use a new variable name with that construct, it will default to type [Hashtable]
until I cast the type as [Array], after which that variable name will always default to type [Array].

Can anyone explain this?
I apologize for the confused description. I'm confused.

Best Regards,

StephenD
dmerida (13) [Avatar] Offline
#2
Re: A Hashtable morphs to an Array in a console session
I am going to take a shot at describing what is happening here. Feel free to scrutinize my answer.

It all depends on the moniker. In some circles, a hastable is also known as an associative array. If you plan on using an array to store multiple key/value pairs, then this is what you are indeed looking for. Otherwise a normal array should suffice.

The default behavior you described, where $a is defined by PS as a hashtable, is correct.

PS C:MyScripts> $a = @{ONE = "One"; TWO = "Two"}
PS C:MyScripts> $a.gettype()

IsPublic.....IsSerial.....Name...............BaseType
--------........--------........------..................--------
True..........True......... Hashtable (or associative array)........ System.Object


Now for the other question.

PS C:MyScripts> [array]$a = @{ONE = "One"; TWO = "Two"}
PS C:MyScripts> [array]$b = @{ONE = "OneOne"; TWO = "TwoTwo"}
PS C:MyScripts> $c
PS C:MyScripts> $c = $a + $b
PS C:MyScripts> $c.gettype()

IsPublic.....IsSerial.....Name...............BaseType
--------........--------........------..................--------
True.........True..........Object[].............System.Array

Because $a was cast as type array, $a maintains that structure even if you change the value of $a. So when you defined $a again later on, it was not actually "defined", you simply changed the value of an array that already existed. That is also why when you defined a new variable, $g, with key/value pairs it instantiated as a hashtable.

So to summarize:

$a = @{ONE = "One"; TWO = "Two"} *this is a new variable, instantiated as a hashtable*
[array]$a = @{ONE = "One"; TWO = "Two"} *this is a new variable, instantiated as a normal array*
After ^
$a = @{ONE = "OneOne"; TWO = "TwoTwo"} *this is the same variable, as a normal array, with a new value*
$g = @{ONE = "One"; TWO = "Two"} *this is a new variable, instantiated as a hashtable*

HTH!
Dave