.NET Action, Func, Delegate, Lambda expression in PowerShell

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".

You May Also Like

About the Author: Reza Aghaei

I’ve been a .NET developer since 2004. During these years, as a developer, technical lead and architect, I’ve helped organizations and development teams in design and development of different kind of applications including LOB applications, Web and Windows application frameworks and RAD tools. As a teacher and mentor, I’ve trained tens of developers in C#, ASP.NET MVC and Windows Forms. As an interviewer I’ve helped organizations to assess and hire tens of qualified developers. I really enjoy learning new things, problem solving, knowledge sharing and helping other developers. I'm usually active in .NET related tags in stackoverflow to answer community questions. I also share technical blog posts in my blog as well as sharing sample codes in GitHub.

3 Comments

  1. 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.

  2. Good stuff — helped me get through some DotNet-Interactive things on which I was working. Thanks, @Reza!

Leave a Reply

Your email address will not be published. Required fields are marked *