In this post I’ll explain what is the equivalent of C# Lambda expression in PowerShell and how you can define and use lambda expressions, Func or Action in PowerShell.
Lambda Expression ↔ ScriptBlock
We can consider PowerShell ScriptBlock as equivalent of C# Lambda expression. It doesn’t mean the specification, type or functionality of ScriptBlock
is the same as lambda expression, they are very different, but in action, wherever you use can lambda expression in C#, in the corresponding case in PowerShell you can use a ScriptBlock
. For example the following table shows what is the equivalent of some C# lambda expression in PowerShell:
C# | PowerShell |
---|---|
() => { ... } |
{ ... } |
x => { ... } |
{param($x) ... } |
(x, y) => { ... } |
{param($x, $y) ... } |
So basically wherever you can use lambda expression in C#, you can use ScriptBlock
in PowerShell, for example:
- Action, Func or other Delegate types
- Lambda event handlers
Action, Func, Delegate ↔ ScriptBlock
Considerig the ScriptBlock
in PowerShell as equivalent of lambda expressions in C#, the same way that you use lambda expressions in C# to define anonymous methods, Func or Action, in PowerShell you use Script blocks. For example the following tables shows the equivalent of some C# Action
or Func
or a specific Delegate
in PowerShell:
C# | PowerShell |
---|---|
new Action(()=>{ ... }) |
[System.Action]{ ... } |
new Action<string>((x)=>{ ... }) |
[System.Action[string]]{param($x) ... } |
new Func<string>(() => { return "Hi" }) |
[System.Func[string]]{ "Hi" } |
new Func<string, string>((x) => { return x }) |
[System.Func[string, string]]{param($x) $x } |
new System.MethodInvoker(() => { ... }) |
[System.MethodInvoker]{ ... } |
For example, the following C# code which defines a Func using a lambda expression:
var f = new Func<string, string, string>((x, y) => { return $"Hello {x} {y}!"; });
In PowerShell, you can define it like this:
$f = [System.Func[string, string, string]]{param($x, $y) "Hello $x $y!" }
As another example, the following C# code which defines a Func using a lambda expression:
Func<string, string, string> f = (x, y) => { return $"Hello {x} {y}!"; };
In PowerShell, you can define it like this:
[System.Func[string, string, string]] $f = {param($x, $y) "Hello $x $y!" }
Invoke Delegate
To invoke a Delegate, Action or Func, you can use Invoke
method and pass parameters to the method. For example, type of $f
in above example is Func<string, string, string>
and you can call it like this:
$f.Invoke("John", "Smith")
Lambda Event Handler ↔ ScriptBlock
The same way that you can hanlde events using lambda event handlers in C#, you can hanle events using script blocks in PowerShell. For example, the following code shows an event hanlder in C# which handles the mouse click event on a form and shows the location of click:
form.MouseClick += (sender, e) => { MessageBox.Show($"{e.Location}"); };
In PowerShell, you can handle the event like this:
$form.Add_MouseClick({param($sender, $e) [System.Windows.Forms.MessageBox]::Show($e.Location)})
ScriptBlock as inline anonymous function
In C#, since lambda expresions don’t have type, they need a context to be resolved. As a result, you cannot assign a lambda expression to an implicit variable defined by var
. But in PowerShell, you can assign a ScriptBlock
to a variable without specifying the type.
Consider the following piece of code in C#:
var f = (int x, int y) => x+y; //Doesn't compile
Above code doesn’t compile in C#, but in PowerShell, you can define a script block and don’t specify the type like this:
$f = {param([int]$x, [int]$y) $x + $y }
Invoke ScriptBlock
The type of $f
in above example is ScriptBlock
and you can call it in either of following ways:
&$f 1 2
Or
&$f -x 1 -y 2
Or
$f.Invoke(1, 2)
Note
You even don’t need to specify type for parameters of ScriptBlock and you can define it like this:
$f = {param($x, $y) $x + $y }
In this case the type, when invoking $f
, if you pass 1
and 2
as parameters, the result will be 3
.
If you pass "1"
and "2"
as parameters, the result will be "12"
.
Great post. it was a very informative post. I hope to read more on the same topic with an example that shows how to use a dll that contains a delegate in a powershell script.
Thank you for a helpful post
Good stuff — helped me get through some DotNet-Interactive things on which I was working. Thanks, @Reza!