What are these lambda expressions?
- A lambda expression is nothing but an anonymous method.
- That is a method that has no access modifier, like public or private,
- and has no name,
- and it has no return statement.
Why do we use them? Why do we use anonymous methods?
For convenience.
- We can write less code and achieve the same thing,
- plus our code would be more readable.
Let me show you this with an example : Let’s say, we would like to write a method that takes a number and returns a square of that number.Typically, this is how we would do this –
using System; namespace LamdaExpressions { class Program { static void Main(string[] args) { Console.WriteLine(Square(5));// 25 } // Write a static method 'Square' that take a parameter 'number'. // it'll return the square of that number. static int Square(int number) { // Return number times number, return number * number; } } }
Here, wrote a static method ‘Square’ that take a parameter ‘number’. It’ll return the square of that number. Make a call to this method. First, I put Console.WriteLine(Square), I’ll set five here, so we should get 25.
Now, with lambda expression, we can achieve the same thing but with less code. Let me show you how it works. The syntax for a lambda expression is something like this: args => expression
. So we have the arguments, and the lambda operator, and some expression. Read this as, args goes to some expression here. For example, if I want to rewrite this method, using a lambda expression, this is how I would do this.
using System; namespace LamdaExpressions { class Program { static object Main(string[] args) { // args => expression number => number * number Console.WriteLine(Square(5)); } // Write a static method 'Square' that take a parameter 'number'. // it'll return the square of that number. static int Square(int number) { // Return number times number, return number * number; } } }
Here the parameter or the argument is number, then goes to number times number. So this is what we call a lambda expression and this code is exactly equivalent to this method. As you see it’s shorter, I didn’t have to specify static, an access modifier like public private, and as the return type or as the argument type. The compiler can automatically infer that in most cases. And if not, we can explicitly specify that.I also didn’t have to write this return statement here. So what we need to do is we need to assign that to a delegate.what a delegate is? A delegate Is a pointer or reference by a method or a group of methods. If you want more about C# Delegate just go through this link. In NET, we have some built-in delegates that you see all the time. For example, we have Func<> and Action<>.
using System; namespace LamdaExpressions { class Program { static object Main(string[] args) { // args => expression //number => number * number Func<int, int> square = Square; Console.WriteLine(Square(5)); } // Write a static method 'Square' that take a parameter 'number'. // it'll return the square of that number. static int Square(int number) { // Return number times number, return number * number; } } }
So Func<> represents a method that takes zero or more arguments and returns a value of type TResult, which is generic, as you can see here. Action<>, on the other side, is another delegate that takes zero or more arguments and returns void. In this case, if you want to use a delegate to point to Square method here we need Func<>. So we can say, Func of int and int. The first parameter here, the first generic parameter here, represents the argument to the method; and the second one represents the data type or the return value. So in this case, because our square method takes an integer and returns an integer, we use Func of int and int. So let’s give it a name. This delegate, as you see, can point to this method without any problems. Now, what they can do is instead of creating that method here, I can just use a lambda expression here. Func<int, int> square = number => number * number;
and I can call this delegate like this. Console.WriteLine(square(5));
Let’s run the application. You get the exact same result 25. So there is no need to write Square method here. I can just get rid of it and the final code for this example is following-
using System; namespace LamdaExpressions { class Program { static void Main(string[] args) { Func<int, int> square = number => number * number; Console.WriteLine(square(5)); } } }
So this is the basic syntax for a lambda expression. On the left side, you’ve got the arguments, the lambda operator, and the expression. If we don’t need any arguments, we need to write a lambda expression like this goes to, and here is the code : ()=> expression
. If we have one argument, we can use just the argument by itself without using parentheses: x=> expression
. And if we have multiple arguments we should always surround them in parentheses (x, y, z) => expression
.
In terms of scope, the lambda expression here has access to all the arguments passed as well as any variables defined inside the method where we define the lambda expression. So, let me show you an example on it :-
using System; using System.Data.Common; namespace LamdaExpressions { class Program { static void Main(string[] args) { const int factor = 5; Func<int, int> multipler = n => n * factor; var result = multipler(10); Console.WriteLine(result); } } }
Let me define a constant call it factor, give a value of five. I want to create a method that takes a number and multiplies that by this factor. So I can use Func<> delegate, the input to that function would be an integer and it returns an integer. I call this function or delegate multiplier and I use a lambda expression to say “n goes to n times factor.” So as you see, we have no compile-time error here. This lambda expression perfectly understands this factor constant inside Lamda method as well as the argument that is passed to it. So let me call this multiplier. Multiplier had a parameter value of 10 And I can put that on console so we should get 50 in result. So, this is the basic of lambda expression.
However let me show you a more practical and common use case of Lamda expressions.
Let take two new class Car.cs and CarRepository.cs :–
using System; namespace LamdaExpressions { public class Car { public string BrandName { get; set; } public int Price { get; set; } } }
using System; using System.Collections.Generic; namespace LamdaExpressions { public class CarRepository { public List<Car> GetCars() { return new List<Car> { new Car(){BrandName="BMW",Price=170000000}, new Car(){BrandName="Toyta",Price=70000000}, new Car(){BrandName="Nissan",Price=50000000} }; } } }
Here I’ve got a class called CarRepository. Let’s say this is responsible for returning the list of cars from the database. Now, to keep things simple here I have just hardcoded a few book objects in a list. So, a method here GetCars()
returns a list of cars and list As you see, it’s a generic type. So it’s a collection of books and here, I am using the object initializer syntax during initialization of the list so that I can immediately populate that list with a few objects as I instantiate each Car. Again, I’m using the object initializer syntax to quickly initialize the car object. So we have three cars. BMW, Toyota and Nissan.
We want to write the code that returns all the cars that are cheaper than $100000000. So, let me show you how we would typically do this without a lambda expression and then, we’ll refactor the code and use a lambda expression instead.
using System; using System.Data.Common; namespace LamdaExpressions { class Program { static void Main(string[] args) { var cars = new CarRepository().GetCars(); var cheapCars = cars.FindAll(IsCheaperThan100MDollers); foreach (var car in cheapCars) { Console.WriteLine(car.BrandName); } } static bool IsCheaperThan100MDollers(Car car) { return car.Price < 100000000; } } }
So first, let’s get the list of cars. So, at this point, our cars variable is of type list of car. Let’s take a look at this object. See, here, in the car list we have FindAll methods here that is used for filtering collections. FindAll method took a argument.Take a look at the argument. Here, we need a predicate of type Car. What is a predicate? A predicate is basically a delegate which points to a method that gets a car, in this case, because it’s of type of Car and returns a boolean value specifying if a given condition was satisfied. So I’m going to create a predicate function (line 20). Let’s call it IsCheaperThan10Dollars.I pass a car here and I return True if Car.Price is less than 100M. So this is what we call a predicate method.It gets an object of type Car, and returns True if a given condition is satisfied.
Look, so, what happens when I call this method and pass a delegate of type predicate? Which means a method like IsCheaperThan100MDollars I can pass that here is cheaper than $100M. Well iterate the collection cheapCars And let’s put that on the console. So I’m going to display the BrandName of the Car. Let’s run this application. So we got Toyota and Nissan. So the code is working.
Now let’s see how we can change this code and use a lambda expression:-
See the problem here is every time we want to call this FindAll (line 11) we have to go and create a method like IsCheaperThan100MDollars and while this is perfectly fine we can achieve this with less code. So why not? change it to var cheapCars = cars.FindAll(car => car.Price < 100000000);
So here, all we have to do is to say, “car goes to car.Price is less than 100000000. So, this lambda expression is exactly equivalent to this method IsCheaperThan100MDollars.
using System; using System.Data.Common; namespace LamdaExpressions { class Program { static void Main(string[] args) { var cars = new CarRepository().GetCars(); var cheapCars = cars.FindAll(c = c.Price < 100000000); foreach (var car in cheapCars) { Console.WriteLine(car.BrandName); } } } }
So again this is a lambda expression. On the left, we’ve got the argument and on the right side, we’ve got the actual expression And ‘=>’ is what we call a lambda operator. We read this expression like this “car goes to car.Price is less than $100000000″. In C#, it’s pretty common to use a single letter when defining lambda expression arguments. So in this case, because we are working on cars, it’s obvious. So, we can just use c. c => c.Price < 100000000
See, the code is even shorter now. Well, that’s it for this article. I hope you enjoy it and thank you for reading.