Powershell 2.0 / 4.0 question

The following line of code works in Powershell 2. It does not work in Powershell 4.

foreach ($acc.DisplayName in $AccountInfo) {$newAccList = $acc.DisplayName + ',' + $NewAccList}

It was changed to this for Powershell 4:

foreach ($acc in $AccountInfo) {$newAccList = $acc.DisplayName + ',' + $newAccList}

The discussion surrounding this line of code is regarding forward-compatibility statements that Powershell 2 is forward-compatible with Powershell 4.

Any thoughts? Thanks in advance!
-Missy

Specifying the property name you want in the foreach assignment is pointless. I’m surprised powershell 2 allowed it, but my testing confirms that it does. Nevertheless it isn’t necessary and doesn’t seem to do anything. Take:

powershell -v 2
$items = Get-ChildItem
ForEach($item.Name in $items) { $item.Length }

The powershell version 4 code you posted will work just as well in version 2.

delete

The disclaimer is this is not my code - I was surprised that this did work in 2.0, but testing showed it actually did work. My question is really “why did this work in 2.0?” and “what was tightened or changed in 4.0 that made it stop working?”

That’s a strange script, maybe there is more to it?

$accountinfo.displayname -join ', ’

Could be that Microsoft didn’t even realize this “worked” in v2. PowerShell v3 was a pretty major rewrite of the engine (adding the new AST, changing from the CLR to the DLR, etc), so the behavior may have changed without anyone really intending or noticing it.

Yes, there’s more to it. It was sent to me to investigate the “forward compatibility issue” so I limited it to just the one line that caused a problem. Merely trying answer the compatibility question to keep to the question posed to me and not perform a code review.

I’m going with never noticed because only one person in the powershell arena would write it like that:D Join was available in 2.0

It may have to do with features introduced in V3 with implicit foreach. In version 2, $service.Name is scalar and appears to have represented the cursor location of $service in $services:

$services = Get-Service
foreach ($service.Name in $services){$service.Name}

In version 3 (and above), implicit foreach, will take a referenced object and perform a for loop automatically which could have caused performance issues. It could also just be a bug that was found and patched because as already mentioned, it’s poor practice since $service is a placeholder versus an object before you get inside the loop construct. My .02 on the matter, but I don’t know if you could get a definitive answer unless it was from the Powershell dev team.

I think, too, that nobody here can really answer your questions of “why” and “what changed.” Sadly, we don’t have that kind of insight, and can only surmise. I’d suggest opening a ticket on UserVoice, which is where the team monitors.

Perhaps more pointedly, I’d suggest that “it doesn’t matter.” What is, is. Now, if the question is, “what is the product team policy on forward compatibility,” they have a goal of minimizing breaking changes. To the point, in fact, where they’ve left some goofy stuff lying around solely to not break things. In this case, as others have surmised, I bet they didn’t know your 2.0 code even worked, as it’s pretty nonstandard programming. So they wouldn’t have known they were breaking it. And as Dave mentioned, the rewrite in 3.0 was likely the culprit.

I would say 99% of the time they’re either forward compatible or are clear about breaking changes. That doesn’t eliminate edge cases like this, though, and it’s just my observation. Nobody in the community can make a definitive statement on behalf of the team, and we can only rarely speak to their intentions.

I will provide the feedback re: the programming, and if pressed for more information about forward compatibility, I will open a UserVoice. Thank you to everyone who responded!!