none
Powershell: Foreach-Object vs. foreach

    Question

  • I am a little confused about this:  Sometimes foreach is an alias for Foreach-Object, and sometimes, it seems, it get interpreted differently, as a construct.  I quote from the 'help about_foreach':

    "The Foreach Statement Inside a Command Pipeline
          When Foreach appears in a command pipeline, Windows PowerShell uses the
          foreach alias, which calls the ForEach-Object command. "

    When I run the following command:

    get-alias -Definition ForEach-Object

    ...I get the following output:

    CommandType     Name                                                                          Definition                                                                  
    -----------     ----                                                                          ----------                                                                  
    Alias           %                                                                             ForEach-Object                                                              
    Alias           foreach                                                                       ForEach-Object 

    However this does not mean that I can use the alias as such:

    % ($x in $y) {"Do something"}

    or

    Foreach-Object ($x in $y) {"Do something"}

    Can anyone shed some light on the behaviour of these two commands/aliases?


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Sunday, August 21, 2011 6:59 AM

Answers

  • Hi,

     

    The answer to the question would depend on given environment and requirement.

     

    There are some good resources around detailed understanding around basic differences and when to use which.

     

    Some resources that I could find it is well explained/discussed:

     

    Windows PowerShell in Action

    http://www.manning.com/payette/

     

    Snippet from the book:

     

    In the case of the Foreach-Object, the statement body is executed as soon as each object is produced. In the foreach statement, all the objects are collected before the loop body begins to execute. This has two implications

     

    First, because in the foreach statement case all the objects are gathered at once, you need to have enough memory to hold all these objects. In the Foreach-Object case, only one object is read at a time so less storage is required. From this, you would think that Foreach-Object should always be preferred. In the bulk-read case, however, there are some optimizations that the foreach statement does that allow it to perform significantly faster than the Foreach-Object cmdlet. The result is a classic speed versus space tradeoff. In practice, though, you rarely need to consider these issues, so use whichever seems most appropriate to the solution at hand.

     

    The second difference is that in the Foreach-Object case, the execution of the pipeline element generating the object is interleaved with the execution of the Foreach-Object cmdlet. In other words, the command generates one object at a time and then passes it to foreach for processing before generating the next element. This means that the statement list can affect how subsequent pipeline input objects are generated. Unlike traditional shells where each command is run in a separate process and can therefore actually run at the same time, in PowerShell they’re alternating— the command on the left side runs and produces an object, and then the command on the right side runs. Executing the foreach statement also defines a special variable for the duration of the loop. This is the $foreach variable and it’s bound to the loop enumerator. (The foreach statement keeps track of where it is in the collection through the loop enumerator.) By manipulating the loop enumerator, you can skip forward in the loop.

     

    Essential PowerShell: Understanding foreach

    http://poshoholic.com/2007/08/21/essential-powershell-understanding-foreach/

    http://poshoholic.com/2007/08/31/essential-powershell-understanding-foreach-addendum/

     

    Why use foreach vs foreach-object.

    http://bsonposh.com/archives/327

     


    Ketan Thakkar | Microsoft Online Community Support
    Wednesday, August 24, 2011 9:06 AM
    Answerer

All replies

  • What I'm getting at, really, what is the effective difference between these two code snippets:

    $dir = gci c:\scripts
    $dir | ForEach-Object { $_.name }
    

    ...and

    $dir = gci c:\scripts
    foreach ($file in $dir) { $file.name }
    


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Sunday, August 21, 2011 7:12 AM
  • Hi,

     

    The answer to the question would depend on given environment and requirement.

     

    There are some good resources around detailed understanding around basic differences and when to use which.

     

    Some resources that I could find it is well explained/discussed:

     

    Windows PowerShell in Action

    http://www.manning.com/payette/

     

    Snippet from the book:

     

    In the case of the Foreach-Object, the statement body is executed as soon as each object is produced. In the foreach statement, all the objects are collected before the loop body begins to execute. This has two implications

     

    First, because in the foreach statement case all the objects are gathered at once, you need to have enough memory to hold all these objects. In the Foreach-Object case, only one object is read at a time so less storage is required. From this, you would think that Foreach-Object should always be preferred. In the bulk-read case, however, there are some optimizations that the foreach statement does that allow it to perform significantly faster than the Foreach-Object cmdlet. The result is a classic speed versus space tradeoff. In practice, though, you rarely need to consider these issues, so use whichever seems most appropriate to the solution at hand.

     

    The second difference is that in the Foreach-Object case, the execution of the pipeline element generating the object is interleaved with the execution of the Foreach-Object cmdlet. In other words, the command generates one object at a time and then passes it to foreach for processing before generating the next element. This means that the statement list can affect how subsequent pipeline input objects are generated. Unlike traditional shells where each command is run in a separate process and can therefore actually run at the same time, in PowerShell they’re alternating— the command on the left side runs and produces an object, and then the command on the right side runs. Executing the foreach statement also defines a special variable for the duration of the loop. This is the $foreach variable and it’s bound to the loop enumerator. (The foreach statement keeps track of where it is in the collection through the loop enumerator.) By manipulating the loop enumerator, you can skip forward in the loop.

     

    Essential PowerShell: Understanding foreach

    http://poshoholic.com/2007/08/21/essential-powershell-understanding-foreach/

    http://poshoholic.com/2007/08/31/essential-powershell-understanding-foreach-addendum/

     

    Why use foreach vs foreach-object.

    http://bsonposh.com/archives/327

     


    Ketan Thakkar | Microsoft Online Community Support
    Wednesday, August 24, 2011 9:06 AM
    Answerer
  • Thanks, Ketan.  Those articles really cleared it up for me:  It's basically memory vs. performance, and I suppose if your know you collection of objects is going to take a lot of memory, it's probably best to use Foreach-Object. 

    But for performance purposes, foreach (at the beginning of a line) is much faster.  Try these two tests:

     

    $ds = 1..50000
    measure-command {$ds | %{$_*9834} }
    

    ...is much slower than:

     

     

    $ds = 1..50000
    measure-command {foreach($item in $ds){$item*9834}}
    

     


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Wednesday, August 24, 2011 9:38 AM
  • Thanks Neo for the detailed explanation.

    Another difference I noticed between Foreach loop and Foreach-Object is, their ability to support loop control statements like break and continue. While these two statements work as expected with foreach loop, they don't have any significance when used inside Foreach-Object. See http://techibee.com/powershell/difference-between-foreach-loop-and-foreach-object-in-powershell/2164 for a few examples about this.


    Thanks,

    Sitaram Pamarthi

    Blog : http://techibee.com

    Follow on Twitter

    This posting is provided AS IS with no warranties or gurentees,and confers no rights

    Tuesday, March 11, 2014 1:20 PM