More on generic collections in Powershell V4, and a gotcha.

In a previous post about generic collections I talked about using the invoke() method of a script block to get a collection.

Boe Prox covered the new Foreach and Where methods of arrays in V4 in this this post .

Turns out they have something in common – they both return the same type of generic collection.

Starting with a generic collection using {}.invoke(), and an array:


$col = {1..10}.invoke()
$col.gettype() | ft -AutoSize


IsPublic IsSerial Name         BaseType     
-------- -------- ----         --------     
True     True     Collection`1 System.Object

$arr = 1..10
$arr.gettype() | Format-Table -AutoSize


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

Running that array through it’s where() method and checking the type returned:

$x = $arr.where({$_})
$x.gettype()| Format-Table -AutoSize

IsPublic IsSerial Name         BaseType     
-------- -------- ----         --------     
True     True     Collection`1 System.Object

Where the Where-Object cmdlet would return an array:


$y = $arr | where {$_}
$y.gettype() | Format-Table -AutoSize


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

Another notable difference is that the where() method will always return that collection even if nothing passed and it’s empty:


$x = $arr.where({})
$x.gettype()| Format-Table -AutoSize

IsPublic IsSerial Name         BaseType     
-------- -------- ----         --------     
True     True     Collection`1 System.Object

Where the cmdlet will return $null:

$y = $arr | where {}
$y.gettype()| Format-Table -AutoSize

You cannot call a method on a null-valued expression.
At line:3 char:1
+ $y.gettype()| Format-Table -AutoSize
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Which can sometimes lead to unexpected results:

Starting with an array of values, and a threshold value to test for:

$arr = -10..10
$Warn = 15

Then test the array for values over the threshold:

$warnings = $arr | where { $_ -gt $Warn } 
  if ($warnings -eq $null)
    { 'All OK' }
   else { 'Over limit' }
All OK

But if we change that to using the where() method:

$warnings = $arr.where({ $_ -gt $Warn }) 
  if ($warnings -eq $null)
    { 'All OK' }
   else { 'Over limit' }
Over limit
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s