Summary: Ed Wilson, Microsoft Scripting Guy, talks about Exploring Windows PowerShell arrays.
Microsoft Scripting Guy, Ed Wilson, is here. One of the problems I had with Windows PowerShell when I first learned it was handling arrays. Why? Because they were so easy. Well, they are easy, but they are also a bit confusing. Why? Because Get-Member seems to hide the type, so I may have an array, and it will report string. But that is something I will talk about in a minute. First, let's look at creating an array.
Create an array in PowerShell
The easiest way to create an array is to simply create a variable and assign more than one item to it. Here is an example:
$a = 1,2,3,4,5
As shown here, if I pipe the $a variable to the Get-Member (gm is an alias) cmdlet, it reports that it is a System.Int32:
PS C:\> $a | gm
TypeName: System.Int32
Name MemberType Definition
---- ---------- ----------
CompareTo Method int CompareTo(System.Object value), int CompareTo(int valu...
Equals Method bool Equals(System.Object obj), bool Equals(int obj), bool...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
GetTypeCode Method System.TypeCode GetTypeCode(), System.TypeCode IConvertibl...
ToBoolean Method bool IConvertible.ToBoolean(System.IFormatProvider provider)
ToByte Method byte IConvertible.ToByte(System.IFormatProvider provider)
ToChar Method char IConvertible.ToChar(System.IFormatProvider provider)
ToDateTime Method datetime IConvertible.ToDateTime(System.IFormatProvider pr...
ToDecimal Method decimal IConvertible.ToDecimal(System.IFormatProvider prov...
ToDouble Method double IConvertible.ToDouble(System.IFormatProvider provider)
ToInt16 Method int16 IConvertible.ToInt16(System.IFormatProvider provider)
ToInt32 Method int IConvertible.ToInt32(System.IFormatProvider provider)
ToInt64 Method long IConvertible.ToInt64(System.IFormatProvider provider)
ToSByte Method sbyte IConvertible.ToSByte(System.IFormatProvider provider)
ToSingle Method float IConvertible.ToSingle(System.IFormatProvider provider)
ToString Method string ToString(), string ToString(string format), string ...
ToType Method System.Object IConvertible.ToType(type conversionType, Sys...
ToUInt16 Method uint16 IConvertible.ToUInt16(System.IFormatProvider provider)
ToUInt32 Method uint32 IConvertible.ToUInt32(System.IFormatProvider provider)
ToUInt64 Method uint64 IConvertible.ToUInt64(System.IFormatProvider provider)
But if I use $a as an input object to Get-Member, it reports system.object[]. The [] means an array. This is shown here:
It is also interesting to look at the .psbase property. This is basically a hidden property, meaning that it does not readily appear and Tab expansion does not seem to show it. It is pretty cool. As shown here, it tells me the length, the rank, and other stuff.
PS C:\> $a.psbase
Length : 5
LongLength : 5
Rank : 1
SyncRoot : {1, 2, 3, 4...}
IsReadOnly : False
IsFixedSize : True
IsSynchronized : False
Count : 5
Also cool is the PSObject property. Note especially, that at the bottom of the output, it says we have three types—one of which is System.Array:
PS C:\> $a.psobject
Members : {Count = Length, int Length {get;}, long LongLength {get;},
int Rank {get;}...}
Properties : {Count = Length, int Length {get;}, long LongLength {get;},
int Rank {get;}...}
Methods : {void Set(int , System.Object ), System.Object&, mscorlib,
Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 Address(int ), System.Object
Get(int ), System.Object GetValue(Params int[] indices),
System.Object GetValue(int index), System.Object GetValue(int
index1, int index2), System.Object GetValue(int index1, int
index2, int index3), System.Object GetValue(long index),
System.Object GetValue(long index1, long index2),
System.Object GetValue(long index1, long index2, long
index3), System.Object GetValue(Params long[] indices)...}
ImmediateBaseObject : {1, 2, 3, 4...}
BaseObject : {1, 2, 3, 4...}
TypeNames : {System.Object[], System.Array, System.Object}
If I use the GetType() method that is automatically created, it tells me that I have an object[] (note the square brackets again) and that my BaseType is an array:
PS C:\> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Use the range operator to save typing
One of my absolutely positively favorite operators is the range operator. It is simply a couple of dots. It will create an array with the numbers in the range. The reason it is so cool is that I can easily create an array with 2 or with 2,000,000 elements in it. It really doesn’t matter. Here is an example:
PS C:\> $b = 1..2000000
PS C:\> $b.Count
2000000
Is it an array? Well, when I use GetType(), it says, yep, it is an array:
PS C:\> $b.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Create a strongly typed array
One of the things that is way cool about Windows PowerShell is that it is a strongly typed language, but it behaves as if it were typeless. What this means is that everything is an object, and every object is a type of something. For instance, in the previous array, the type was System.Array, but the array held. An int32 holds numbers from -2147483648 to 2147483647 in size. This is shown here:
PS C:\> [int32]::MaxValue
2147483647
PS C:\> [int32]::MinValue
-2147483648
int32 is the default. But what if I don’t need a number that big? Well, I can change to int16. As you can see here, int16 has a maximum value of 32767:
PS C:\> [int16]
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int16 System.ValueType
PS C:\> [int16]::MaxValue
32767
If I want to ensure that my array does not change, I can use [int16[]] to constrain the type or to keep it from changing. If I try to assign a number that is too large, it generates the following error message:
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy