Author Posts

December 31, 2016 at 3:21 pm

Hi,
I encountered a weird problem with foreach loop. My understanding is foreach is alias of foreach-object – which I can confirm by using get-alias command.
However if I run the following command, I get different results with foreach & foreach-Object, below is simple conde what I have tried, can someone explain why there is a difference in behaviour, is it a bug or expected behaviour?

$list = "A", "B", "C", "D"

PS C:\> ForEach ($item in $list) {$item}
A
B
C
D
PS C:\> ForEach-Object ($item in $list) {$item}
At line:1 char:23
+ ForEach-Object ($item in $list) {$item}
+ ~~
Unexpected token 'in' in expression or statement.
At line:1 char:22
+ ForEach-Object ($item in $list) {$item}
+ ~
Missing closing ')' in expression.
At line:1 char:31
+ ForEach-Object ($item in $list) {$item}
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken

December 31, 2016 at 4:22 pm

You are partially right and partially wrong 🙂

"Foreach" are just 7 letters that PowerShell will have to parse in two different ways, depending on the context.

1. As you correctly mentioned, they could be an alias for a Cmdlet called Foreach-Object. Other alias is %, but you've already found them with Get-Alias.
To be understood as such a cmdlet, you have to use it in a pipeline. In your example :

     $list | Foreach-Object -Process { $_ }
   

This could be abbreviated with the alias and using default parameters to

     $list | Foreach { $_ }
   

But I wouldn't recommend it. Do not use aliases, they could have been modified to do a different thing...

2. "Foreach" can also be a keyword, a language structure used to enumerate any object which can be enumerated.
The syntax is totally different (similar to foreach in C#, for example), and is NOT translated to a cmdlet.

   foreach ($element in $list) { $element }
   

Notice in this case you don't use $_ but a variable you explicitly declare ($element in this example)

Unfortunately they chose "foreach" for both the keyword and the alias, which makes things slightly difficult.

Homework : Foreach-Object has also a -Begin and -End parameter...

January 1, 2017 at 7:26 pm

Many thanks Ruiz, that explains the change in behaviour... Using alias as foreach for foreach-object confused me a bit