With PowerShell there's historically been no need for yield return; since that's essentially what the pipeline is.
However, with PS5's classes, methods cannot write to the pipeline. As such, are there any options to mimic yield return / pipeline behaviour from a Powershell class method?
Demo
Function
This code returns data to the pipeline; we can see that the variable $global:i is updated by the function, then the value's read by the next step in the pipeline before the next iteration of the function:
[int]$i = 0
function Get-PowerShellProcesses() {
Get-Process | ?{$_.ProcessName -like '*powershell*'} | %{$global:i++; $_}
}
Get-PowerShellProcesses | %{"$i - $($_.ProcessName)}
Output:
1 - powershell
2 - powershell_ise
Class Method
If we do the same with a class's method everything's the same except that the full result set is gathered before being passed on to the pipeline.
[int]$i = 0
class Demo {
Demo(){}
[PSObject[]]GetPowershellProcesses() {
return Get-Process | ?{$_.ProcessName -like '*powershell*'} | %{$Global:i++; $_}
}
}
$demo = New-Object Demo
$demo.GetPowerShellProcesses() | %{"$i - $($_.ProcessName)"}
Output:
2 - powershell
2 - powershell_ise
I'm guessing there's no solution; but hoping there is something.
Why does this matter?
In the above example obviously it doesn't. However, this does have an impact where we don't need the full result set; e.g. say we had a | Select-Object -First 10 after the function call, but had an expensive operation returning thousands of results, we'd see a significant performance hit.
What have you tried?
Inline Return:
Get-Process | ?{$_.ProcessName -like '*powershell*'} | %{return $_}
Error: Not all code path returns value within method.
Inline Return + Final Return:
Get-Process | ?{$_.ProcessName -like '*powershell*'} | %{return $_}
return
Error: Invalid return statement within non-void method
Inline Return + Final [void] / $null Return:
Get-Process | ?{$_.ProcessName -like '*powershell*'} | %{return $_}
return [void] #or return $null
No error; but acts as if only the last return statement were called; so we get no data.
Yield Return:
Get-Process | ?{$_.ProcessName -like '*powershell*'} | %{yield return $_}
Error: The term 'yield' is not recognized ...
Workaround
The simple workaround is to use C# classes with yield return, or traditional PowerShell functions instead.