This article is the third one from a series of 3 articles on C# delegates. If you are new to delegates and haven’t gone through the previous ones, I suggest you to go through them first
We all might have read articles that say “If you are using lambda expressions in C#, you are already working with delegates” but they don’t discuss anything about how they are closely related.
In this article we will discuss the journey from delegate to lambda expressions.
Below we have a person class with two properties.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
We have a function somewhere outside this class which takes a Person parameter and returns formatted name
public string GetFullName(Person person)
{
return $"{person.FirstName} {person.LastName}";
}
Lets declare a delegate for the function which should match the signature.
public delegate string PersonFormatter(Person person);
Using above delegate with our function will be like this
var person = new Person { FirstName = "John", LastName = "Doe" };
PersonFormatter formatter = GetFullName;
var fullName = formatter(person);
Here we have a separate function for our delegate, but for most of our day-to-day programming we don’t need to write a separate function for our delegate to be used.
We can achieve use a delegate by using something known as Anonymous functions in C#. Below is how we can do that.
PersonFormatter formatter = delegate (Person person)
{
return $"{person.FirstName} {person.LastName}";
};
// No changes in the way delegate is invoked
var fullName = formatter(person);
The syntax has 4 major parts
a variable named formatter of type PersonFormatter
use of delegate keyword
Person variable in round brackets
a function body that does the same as our GetFullName function earlier. This function body does not has a name, hence an Anonymous function.
We can simplify the use of anonymous function while we initialize our delegate. We can get rid of the ‘delegate’ keyword and use ‘=>’ which is commonly knows as ‘goes to’ operator or famously in our case as the ‘lambda’ operator.
PersonFormatter formatter = (Person person) =>
{
return $"{person.FirstName} {person.LastName}";
};
We removed the delegate keyword, and added a lambda operator after our Person variable.
We can simplify this even more. Taking advantage of C#’s Type Inference, we can also get rid of the Person type and just use a parameter name as shown below.
PersonFormatter formatter = (person) =>
{
return $"{person.FirstName} {person.LastName}";
};
We got rid of the type Person, and are just using person as a parameter . C#’s Type inference automatically kicks in due to the delegate type PersonFormatter that the parameter it needs is of Person type.
Interesting till now ? More on the way.
We can simplify this even further. It happens, if we are working with single parameter delegates, we don’t even need the brackets around the parameter as well.
PersonFormatter formatter = person =>
{
return $"{person.FirstName} {person.LastName}";
};
Below, I have renamed person to ‘p’ for simplification.
PersonFormatter formatter = p =>
{
return $"{p.FirstName} {p.LastName}";
};
This is what we call as “Statement Lambdas”, meaning expressions are enclosed in braces.
We can simplify this even further. If our anonymous function body has only one statement, we can get rid of curly brackets and the return keyword as well.
PersonFormatter formatter = p => $"{p.FirstName}{p.LastName}";
This is called as “Expression Lambdas”
If we are working with more that one parameters, we have to use brackets around our parameter
public delegate int DoSomeMath(int a, int b);
// Below is to add two numbers
DoSomeMath someMath = (a, b) => a + b;
Hope the articles helped to bridge the gap between delegates and lambda expressions.
Top comments (0)