You really only need ForEach-Object if you’re doing something more complex, or if the command you want to pipe input to does not support pipeline input. Restart-WebAppPool does support piping the -Name argument by property name, and the objects output by your Get-ChildItem command have a Name property that is exactly what you needed. The end result of these two commands are identical (though the ForEach-Object version will not execute as fast):
gci IIS:\apppools | Restart-WebAppPool gci IIS:\apppools | ForEach-Object { Restart-WebAppPool -Name $_.Name }
There’s technically no “collection” in either of those commands. The pipeline works by streaming one object at a time, and at no point are the entire results of Get-ChildItem saved in a collection. However, PowerShell does do some behind the scenes work when it comes to actual collections and the pipeline. For example:
# set up our array $directories = @('C:\', 'C:\Windows','C:\Program Files') # Pipe the array to a command $directories | Get-ChildItem
In this case, PowerShell isn’t sending the array object itself to Get-ChildItem; it automatically sends the objects contained in the array, one at a time.
There’s a lot of information on this topic in the about_Pipelines help file.