This is a series I created on my company's internal intranet for a few young developers. However, I thought it might be useful to anyone, so I wanted to make it public.
In my last post, I explained how to use anonymous methods, or inline delegates, to remove a bunch of unnecessary code from your class. This post is going to explain how lambda expressions are really just a syntatic helper to aid in the removal of more 'extra' code and to make anonymous methods a little more readable.
And that's really what lambda expressions are - cleaner ways to write anonymous methods/inline delegates.
Let's look at our example from last time. To handle two different filtering scenarios, we had this:
1: IList<TeamDTO> allTeams = new List<TeamDTO>
2: {
3: new TeamDTO("Flyers", "East"),
4: new TeamDTO("Blackhawks", "West"),
5: new TeamDTO("Blue Jackets", "West"),
6: new TeamDTO("Capitals", "East")
7: };
8:
9: IList<TeamDTO> easternTeams = SelectTeamsByFilter(allTeams, delegate(TeamDTO team) { return team.Conference == "East"; });
10:
11: IList<TeamDTO> teamsThatStartWithLetterB = SelectTeamsByFilter(allTeams, delegate(TeamDTO team) { return team.TeamName.StartsWith("B"); });
This isn't bad, but you still have to use the delegate keyword and declare a function, complete with parentheses and curly braces inline. That can get hard to match up pretty quickly. So here are these same lines using lambda expressions:
1: IList<TeamDTO> allTeams = new List<TeamDTO>
2: {
3: new TeamDTO("Flyers", "East"),
4: new TeamDTO("Blackhawks", "West"),
5: new TeamDTO("Blue Jackets", "West"),
6: new TeamDTO("Capitals", "East")
7: };
8:
9: IList<TeamDTO> easternTeams = SelectTeamsByFilter(allTeams, team => team.Conference == "East");
10: IList<TeamDTO> teamsThatStartWithLetterB = SelectTeamsByFilter(allTeams, team => team.TeamName.StartsWith("B"));
As I said earlier, this is really just a cleaner way to write the delegate. The left side of the lambda expression declares the inputs. You will often see these as x. That's just a convention. I chose team because I think it's more descriptive. The right side of the lambda expression holds the statement block, or function body. Pretty simple - lambda expressions are delegates. Nothing to be afraid of.
A few notes about lambda expressions before this post is over.
When a lambda expression's body contains only one line of code, you don't need a return - the result of that line of code is assumed to be the return value. So above, the line evaluates to a boolean, so that is considered the return value. That said - you CAN write lambda expressions containing multiple lines of code, but you then have to include the return keyword and wrap your expression body in curly braces. Here's a quick example:
1: return SelectTeamsByFilter(allTeams, team => {
2: int count = team.TeamName.Length;
3: return count == 10;
4: });
Not super realistic, it filters by teams whose name is ten characters long.
Also - lambda expressions can take zero parameters. In that case, you use an empty set of parentheses on the left side like this:
And they can also take multiple inputs. For example, if you wanted to compare two teams:
1: (team1, team2) => team1.TeamName == team2.TeamName
So there you go. Lambda expressions are nothing more than clean ways to write delegates. And delegates are a really powerful and useful feature to allow you to separate a method from its implementation.
There's going to be one more post in this series. It's a bit of a tangent rather than a continuation, but I wanted to introduce a few classes that .NET provides to help facilitate the use of delegates in your code. So look for that in the next couple of days.