Old School PowerShell Expressions vs New

In a recent StackOverflow answer, I wrote the following PowerShell to find parameters that were in a given parameter set (edited somewhat for purposes of this post):

$commandName='Get-ChildItem'
$ParameterSetToMatch='LiteralItems'

$ParameterList = (Get-Command -Name $commandName).Parameters.Values

foreach($parameter in $parameterList){
    $parameterSets=$parameter.ParameterSets.Keys
   if ($parameterSets -contains $parameterSetToMatch ){
        write-output $parameter.Name
    }
}

A quick note…it’s not correct. It only shows parameters that are explicitly in the parameter set. Items that aren’t marked with any parameter set are in all parameter sets, and this doesn’t include them. That is beside the point.

Note that I’m looking through collections with a loop and an if statement.

A bit better

I could have made it a bit better with Where-Object (it’s still a bit bad because hashtable iteration isn’t nice):

$ParameterList.GetEnumerator() | 
   Where-Object {$_.Value.parameterSets.Keys  -contains 'Items'} | 
   Select-Object -Property Key

The “new” way

When I say new, I mean “PowerShell 3.0 new”. I still have a lot of PowerShell 1.0 muscle-memory that I need to get rid of. This post is part of the attempt. 🙂

Now, I’m going to use two features that were added to PowerShell 3.0 that I don’t use often enough: Member Enumeration and Where().

Member Enumeration says I can refer to members of the items in the collection through the collection.

For instance,

(Get-ChildItem -file).Length

Get-ChildItem returned a collection of files which each have a length property.

So instead of using ForEach-Object or Select-Object, I can use dot-notation against the collection and get the properties of the items in the collection. Nifty shortcut.

The second feature I’m going to use is the Where() method. This method is available with any collection object, and is (in the simplest case) just like using Where-Object.

Putting those two together, I get this:

$ParameterList.GetEnumerator().Where{$_.Value.parameterSets.Keys  -contains 'Items'}.Key

What is amazing about this to me isn’t how short it is (although it is short).

The amazing part is that I logically looped through a collection of objects looking for items in the collection which matched specific criteria, then extracted a particular property of those objects….and I didn’t need to use a pipeline at all.

I’m a big fan of pipelines, and the general-purpose *-Object cmdlets allow us to manipulate data with ease. However, that power comes at a price. Pipelines cost memory and time. This expression doesn’t incur the “penalties” of using a pipeline but gets us all of the benefit.

What do you think? Is the new version better?