C# LINQ Background Topics


Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

Extra credit - Action and Func

Feeling a bit overwhelmed? The content on this page is optional. It can make your life easier, but it requires a bit more knowledge to understand than the other content in this course. Feel free to skip to the next lesson if you want to.

Writing a delegate type for each delegate that you want to declare gets a bit repetitive. For example, suppose you were to write this SayHello delegate:

private delegate void SayHello();

private SayHello helloFunction = () => Console.WriteLine("Hello!");

Looks good, right? But imagine if you later wanted to declare another delegate that can say goodbye? You could reuse the SayHello type, but that doesn't make much sense, does it?

You could instead declare a new delegate type:

private delegate void SayGoodbye();

private SayGoodbye goodbyeFunction = () => Console.WriteLine("Goodbye!");

Notice that SayGoodbye is, other than its name, exactly the same as SayHello. Maybe it would be better to rename SayHello to something more generic like SayAnything...

private delegate void SayAnything();

private SayAnything helloFunction2 = () => Console.WriteLine("Hello!");
private SayAnything goodbyeFunction2 = () => Console.WriteLine("Goodbye!");

Then what do you do when you need to declare another delegate type that also takes no parameters and returns void? Maybe that declaration should be called DoAnything! But then you'd need to declare that type for every project that you work on...

See where this is headed?

Action type

There is a family of built-in delegate types that can be used to declare delegate variables without the need to define a custom type. The types that represent a delegate without a return value (void return) are the Action types in the System namespace.

Here is an example using Action to declare a delegate variable:

private Action supFunction = () => Console.WriteLine("Sup?!");

What if you want to pass some parameters to your delegate? That's covered as well. There's an Action<T> that takes one parameter, or Action<T1, T2> that takes two parameters, and so on all the way up to an Action that takes 16 parameters.

Here's an example of a delegate that takes three parameters of different types:

private Action<string, int, bool> printThreeValues =
    (s, i, b) => Console.WriteLine($"string: {s}, int: {i}, bool: {b}");

Func type

Action is good for delegates that return void, but what about delegates that return a value? That's where Func<TResult> comes in. The Func family of delegate types can return a value of any type you wish. For example:

private Func<int> twoPlusThree = () => 2 + 3;

What about passing parameters? Then you need Func<T, TResult> for delegates that take one parameter, and Func<T1, T2, TResult> for two parameters, etc. Just as with Action, the framework has delegates that support all the way up to 16 parameters.

Here is an example of a delegate declaration that takes two string parameters and returns an int:

private Func<string, string, int> sumCharacters = 
    (s1, s2) => s1.Length + s2.Length;
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content