Practical Introduction to Lambda Expressions
Popularized by Python and Ruby, the lambda expression is a powerful shorthand that can be used to significantly speed up c# development. This post deals entirely with using lambda expressions in everyday development, and sidesteps the esoteric mathematical logic that makes them intimidating.
A Lambda expression in c# is simply a piece of syntactical sugar for fleshing out a function body where you would normally plug in a delegate (pointing to a function somewhere else). This saves you two or three lines of code per call, speeding up your development (where delegates are required) to light speed and making your code more maintainable.
Because lambdas can only be used where delegates are required, your initial benefit from learning them may be limited. Before looking into lambdas, I avoided using functions in the .NET base class library that required delegates because of the added hassle. Now, after learning how to use lambdas, I seek them out!
Lastly, are you familiar with anonymous methods? Lambda expressions are very similar - just a slightly shorter syntax. Anonymous methods and lambdas compile to the same intermediate language (and have the same performance as a result).
What does a lambda expression look like?
In the example above, Name => Name.StartsWith(“O”) is the lambda expression. All it does is check if the “Name” passed into it starts with a given letter and returns True/False. The Find() function (not lambda-related) runs this lambda expression against each list item until a match is found. You could use a delegate to another function (like the one below) or an anonymous method in its place, but it would be a lot more code either way.
This expression is roughly equivalent to the non-lambda function:
(Which could have been plugged into FruitNames.Find() using a delegate by the way. All that was accomplished by using the lambda was saving a few lines of code.)
Name is the function argument. We could have named this “FruitName”, “F”, or anything else. However, we would have had to remember to change it in the function body at the same time. Lambdas automatically infer variable types from the parent signature. In this case, StartsWith() requires a single string argument, causing “Name” to typed as a string.
This is the important symbol that tells c# that you are using a lambda expression. It is absolutely required for every lambda expression that you write. Arguments go on the left and your function body goes on the right. Read as “goes to”.
Is plain c# and also the meat of the expression. This simply returns true if the function argument “Name” begins with the letter “O” or false if it does not. In this example, it’s only one line. However, lambdas may be expanded to multiple lines (just wrap your function body in squiggly brackets like any other method) In this case, it is required that we return a Boolean because the parent “Find()” requires a Predicate (Boolean return type):
(Predicate simply takes in one argument of a given type and returns a Boolean)
Now that you have a basic understanding of what a lambda expression is, and how it might be useful (less code), take a look at a few practical code examples.
A predicate is just a function that returns true or false. Imagine helping a friend sort through a box of old items. You pick up each item out of the box and your friend (after looking at the item) either says “throw away” or “keep”. Your friend is acting as a predicate.
Predicates are extremely useful for filtering lists of items and you will find them throughout the framework for this reason. In the first example in this article we used a predicate to sort through a list of fruit by looking at the first letter of each fruit name.
Here is another example using objects instead of strings:
In this example “BooksPublishedAfter1995()” uses a lambda expression as a predicate to compare each when each book was published to a specific date. This function returns a new collection of books containing just SICP and Pragmatic Programmer.
Here’s the a similar multiline lambda that returns books published between 1991 and 1997:
As you can see, it would be excessive to type out a separate function just for this simple piece of logic. Lambda statements are ideal for this type of filtering.
Don’t Forget to stay DRY
(Don’t Repeat Yourself) Lambdas and anonymous methods are a power tools that should be used carefully. Remember to identify and move common predicates into shared functions early instead of using repeated Lambdas throughout your code and creating a maintenance nightmare.
Absolutely Minimalistic Threading
It is possible to spawn new threads using just the code contained in the lambda statement. In fact, you can do it in only a few lines. A good example for this is when you need to open up a webpage in the default browser from a windows forms application but don’t want the user interface to skip a beat or lock up (as is the case with some firewall software). Lambda expressions paired with a new thread will do the trick:
If you look carefully, you will notice that “()” is used on the left hand side of the lambda. This simply indicates that no arguments are to be used.
For more cool threading lambda expression examples for c#, have a look at my Threading Tips and Tricks post.