Lambda Expressions
A lambda expression is a small method with no name, written where it's used, such as name => name.Length > 4. Pass one to a method like FindAll, RemoveAll or Sort, and that method runs it on each item.
Apprentice · C# · Updated
After this lesson you can
- Write a lambda expression with its parameters, an arrow and a body, and read one aloud
- Pass a lambda to a method such as FindAll, RemoveAll, Exists or Sort
Key takeaways
- A lambda such as
name => name.Length > 4is a method with no name: its parameters, the=>arrow, then its body. Read=>aloud as "goes to" or "such that". - Pass a lambda to
FindAll,Find,ExistsorRemoveAll, and the method does the looping while your lambda decides about one item at a time. - Two parameters go in parentheses, as in
names.Sort((a, b) => a.Length.CompareTo(b.Length)); a body with more than one statement needs braces and areturn. - A
Func<string, bool>holds a lambda that takes astringand returns abool(the last type is the return type); anAction<string>returns nothing.
Some methods need to be told how to do part of their job. A list can find every name you want, but it can't know which names you want. So you hand it a tiny method that answers "is this one of them?" for a single name, and the list runs it on each one.
Writing a whole named method for that would be a lot of ceremony for one line. A lambda expression is the short form: a small method with no name, written right where it's used.
The shape of a lambda
name => name.Length > 4
Read the => aloud as "goes to" or "such that": name such that name's length is more than 4.
| Part | Here | Means |
|---|---|---|
| Parameters, before the arrow | name |
What the lambda is given: one name |
| The arrow | => |
Separates the parameters from the body |
| The body, after the arrow | name.Length > 4 |
What it works out: true or false |
It's the same as this method, minus the name, the types and the return:
bool IsLong(string name)
{
return name.Length > 4;
}
C# works out the parameter's type from where the lambda is used, so you rarely write it.
Giving a lambda to a method
List<T> has methods that take a lambda. FindAll runs it on each item and returns a new list of the items it said true for:
List<string> names = new List<string> { "Olivia", "Ethan", "Ava", "Liam", "Sophia", "Mia" };
List<string> longNames = names.FindAll(name => name.Length > 4);
List<string> startWithA = names.FindAll(name => name.StartsWith("A"));
Console.WriteLine(string.Join(", ", longNames));
Console.WriteLine(string.Join(", ", startWithA));
Olivia, Ethan, Sophia
Ava
Each call gets a different lambda, so each finds different names. FindAll does the looping; the lambda only decides about one name at a time.
More List<T> methods that take one:
List<int> scores = new List<int> { 72, 95, 48, 88, 61 };
Console.WriteLine(scores.Exists(score => score >= 90));
Console.WriteLine(scores.Find(score => score < 50));
scores.RemoveAll(score => score < 60);
Console.WriteLine(string.Join(", ", scores));
True
48
72, 95, 88, 61
| Method | Runs the lambda on each item, and |
|---|---|
FindAll(...) |
returns a new list of the items it's true for |
Find(...) |
returns the first item it's true for (or the default, such as null or 0) |
Exists(...) |
returns true if it's true for any item |
RemoveAll(...) |
removes every item it's true for, and returns how many |
More than one parameter
When a lambda needs two parameters, put them in parentheses. Sort compares two items at a time, and needs to know which goes first:
List<string> names = new List<string> { "Olivia", "Ethan", "Ava", "Liam" };
names.Sort((a, b) => a.Length.CompareTo(b.Length));
Console.WriteLine(string.Join(", ", names));
Ava, Liam, Ethan, Olivia
a.Length.CompareTo(b.Length) is negative when a is shorter, so shorter names go first.
And when the body needs more than one statement, give it braces and a return, like a method's body:
List<int> scores = new List<int> { 72, 95, 48, 88 };
List<int> passes = scores.FindAll(score =>
{
bool passed = score >= 60;
return passed;
});
Console.WriteLine(passes.Count);
3
Lambdas in variables
A lambda can be kept in a variable, and called like a method. Its type says what it takes and returns: Func<string, bool> takes a string and returns a bool (the last type is always the return type), and Action<string> takes a string and returns nothing:
Func<int, int> square = number => number * number;
Func<string, bool> isLong = name => name.Length > 4;
Action<string> greet = name => Console.WriteLine( quot;Hello, {name}!");
Console.WriteLine(square(7));
Console.WriteLine(isLong("Ava"));
greet("Ada");
49
False
Hello, Ada!
Func and Action are delegates: types for "a method that takes these and returns that". You won't often write them yourself, but you'll see them in the descriptions of methods that take lambdas, such as Where(Func<T, bool> predicate) in the next lesson.
Check yourself
2 questions to try on the lesson page.
So what
A lambda is a method small enough to write in the middle of a line. Hand one to a method, and that method does the looping while your lambda makes the decision. That's the whole idea behind LINQ, next.