Where() method in powershell 4 breaks my objects!

Page content

Boe Prox wrote an excellent post on the new Where() and Foreach() methods in Powershell Version 4 over at his blog:

http://learn-powershell.net/2013/11/26/checking-out-the-where-and-foreach-operators-in-powershell-v4/

I decided to play around with these a bit and discovered a behavior I didn’t expect. When using the Where() method instead of Where-Object, the output differ and I can no longer access and update my original object. This is because Where() always returns a collection of objects (even if it’s only a collection of one object).

To describe the issue more detailed I will give an example. Lets say that I have an ArrayList of PSCustomObjects and want to filter out one of these objects and update a property on that object.

Start by creating an ArrayList and add two objects to the list. In real life the objects would have more properties and the list would be much longer but this is just an example.

$list = New-Object -TypeName System.Collections.ArrayList
1,2 | Foreach {
    $object = [PSCustomObject]@{
        ID = "$_"
        Array = @("first","second")
    }
    [void]$list.Add($object)   
}

Now lets say that I want to filter out one object based on its ID and add something to the attribute Array. Doing this the “old fashioned” way from powershell v3 with Where-Object works like a charm.

$entry1 = $list | Where-Object {$_.ID -eq 1}
$entry1.Array += "third"
$list

This will produce the following output:

Where-Object_1

So far so good! Now lets try the new Where() method. The following code should in my understanding do the same thing in powershell version 4:

$entry2 = $list.Where({$_.ID -eq 2})
$entry2.Array += "third"
$list

But that is not the case at all! Now I get the following output:

Where()_1

“The property cannot be found on this object. Verify that the property exists and can be set.”

Comparing $entry1 with $entry2 by using Get-Member doesn’t help much either…

WhereGetMember

But using GetType() shows something more interesting!

Where_GetType

$entry2 has Name = Collection`1 instead of Name = PSCustomObject as $entry1.

The collection object has a few properties as Add and Remove but doesn’t expose my objects properties.

To access the properties of the original object I have to index into the collection like this:

$entry2[0].Array += "fourth"
$list

And now my original list gets updated:

Updated List

An alternative is to use the Item-property like this:

$entry2.Item(0).Array += "fifth"