We created a variable called "a" and gave it a value of 1. Now it is an Int32 type variable. Now what happens when we change the value to a string?PS C:\> $a = 1PS C:\> $a | gmTypeName: System.Int32
PS C:\> $a = "one"
PS C:\> $a | gm
TypeName: System.StringSame variable is now a string! The magic of dynamically-typed scripting in action. Just for fun here's something else:
PS C:\> $a = 1
PS C:\> $b = "2"
PS C:\> $b | gm
TypeName: System.String
PS C:\> $a + $b
3The second variable is a string, but PowerShell saw we were trying to combine an int and a string, and it checked to see if the string could convert to an int. It could, so it added the two and produce an int output. Neat, huh?
See I've declared an array, and it is just an Object array so it can hold any type of content; int, string, boolean.PS C:\> $a = @()PS C:\> Get-Member -InputObject $aTypeName: System.Object[]
Now I've got three objects in my array, and I can find that out by accessing the Count or Length property (count is an alias for length).PS C:\> $a = (1,"two",$false)PS C:\> Get-Member -InputObject $aTypeName: System.Object[]
PS C:\> $a.Length
3
PS C:\> $a.Count
3What if I tried to populate the array using a Cmdlet call?
PS C:\> $a = Get-Process
PS C:\> $a.Length
128Boom, I've got 128 processes running. That's a lot, maybe I should see what is going on...later. This is great, but what happens if my call only returns a single process?
PS C:\> $a = Get-Process | select -First 1
PS C:\> $a.length
1
PS C:\> Get-Member -InputObject $a
TypeName: System.Diagnostics.ProcessUh-oh. My super sweet array is no longer an array, it's a process object! Luckily the process object has a length property, so I am still getting a value back. But. I have found instances where the length property does not exists, and suddenly instead of getting a 1 back for the length, you get nothing. That could really screw things up if you are checking length to determine if your array is empty, like "$a.length -gt 0" now returns false if there is no length property. The solution? Strong-typing like such:
PS C:\> [array]$a = @()
PS C:\> Get-Member -InputObject $a
TypeName: System.Object[]
PS C:\> $a = Get-Process | select -First 1
PS C:\> Get-Member -InputObject $a
TypeName: System.Object[]Sweetness. We've still got our array with all its properties. My advice, when declaring a variable, think whether the type is super important to you. If so, make sure to strong-type it like above.
Labels: powershell, scripting, Scripts