C# Lambda Expressions: Why Should I Use Them

C# Lambda expressions: Why should I use them?

Lambda expressions are a simpler syntax for anonymous delegates and can be used everywhere an anonymous delegate can be used. However, the opposite is not true; lambda expressions can be converted to expression trees which allows for a lot of the magic like LINQ to SQL.

The following is an example of a LINQ to Objects expression using anonymous delegates then lambda expressions to show how much easier on the eye they are:

// anonymous delegate
var evens = Enumerable
.Range(1, 100)
.Where(delegate(int x) { return (x % 2) == 0; })
.ToList();

// lambda expression
var evens = Enumerable
.Range(1, 100)
.Where(x => (x % 2) == 0)
.ToList();

Lambda expressions and anonymous delegates have an advantage over writing a separate function: they implement closures which can allow you to pass local state to the function without adding parameters to the function or creating one-time-use objects.

Expression trees are a very powerful new feature of C# 3.0 that allow an API to look at the structure of an expression instead of just getting a reference to a method that can be executed. An API just has to make a delegate parameter into an Expression<T> parameter and the compiler will generate an expression tree from a lambda instead of an anonymous delegate:

void Example(Predicate<int> aDelegate);

called like:

Example(x => x > 5);

becomes:

void Example(Expression<Predicate<int>> expressionTree);

The latter will get passed a representation of the abstract syntax tree that describes the expression x > 5. LINQ to SQL relies on this behavior to be able to turn C# expressions in to the SQL expressions desired for filtering / ordering / etc. on the server side.

when to use or not Lambda Expressions

There are somewhat two questions here.

First, as for your example, using a lambda vs. using the anonymous delegate syntax. The generated code by the compiler will be identical, so it does not come down to a performance difference, but rather a readability difference.

Personally, I find the lambda syntax easy to follow. I find that the lambda syntax is almost always cleaner, more concise, and more understandable than the anonymous delegate syntax, so I prefer it nearly always.

As for using lambda expressions throughout the code - Personally, I am a fairly heavy user of them. I find that they often make life much easier than having lots of methods defined. If a piece of code is not going to be reused by any other methods (it will only be called and exist in one place), I will use a lambda to express it.

If a piece of code is going to be used more than once, it should be pulled out into a (non-anonymous) method. Also, if a piece of code is something that could and should be tested, I tend to make a method for it, since that eases testability.

Why do I use lambda expressions instead of functions?

Firstly I want to correct this:

use lambda expressions instead of functions

What you are showing in your example, as Daniel has pointed out in his answer, is just an expression bodied member.

The use of an expression bodied over a method is not a standard, but more of a feature that is supported by the C# language, so it is up to you when you want to use it and when not.

I would always use expression bodied members instead of methods, for short methods bodies that fit the monitor, but this is going to a primary opinion based answer.

Secondly, for the return y.Length > x ? true:false; section, I will expand this with an example. If you hold the value of the y.Length > x into a variable, it would look like this:

bool condition = y.Length > x;

and then the return would look like this:

return condition ? true : false;

Now you will see that it is more intuitive to return directly the condition.

return condition;

Performance Benefits of Lambda Expressions

Lambda expressions are not more performant, they are just simpler. They are mainly used for:

  • Creating delegates
  • Creating expressions for LINQ
  • Putting local variables in captures for delegates

When creating a delegate, the code that the compiler creates is just like if you would have created a named method, and got a delegate to that method.

Func<int, int> mul = n => n * 2;

compared to:

public static int Mul(int n) {
return n * 2;
}

Func<int, int> = Mul;

When creating an expression, the compiler creates an expression tree that can either be turned into a delegate or used by a LINQ provider to be translated into something else. The Linq To Sql provider for example would translate the expression into SQL code.

When creating a delegate that uses a local variable that is declared in the method that creates the deleage, a closure object is automatically created where that variable resides, instead of putting the variable on the stack. This is similar to how you would make the variable available to a named method by making it a field in the class where the method is declared.

int x = 2;
Func<int, int> mul = n => n * x;

compared to:

public class Closure {

public int x;

public int Mul(int n) {
return n * x;
}

}

Closure c = new Closure;
c.x = 2;

Func<int, int> mul = x.Mul;

What's the point of a lambda expression?

First: brevity and locality:

Which would you rather write, read and maintain? This:

    var addresses = customers.Select(customer=>customer.Address);

or:

static private Address GetAddress(Customer customer)
{
return customer.Address;
}

... a thousand lines later ...

var addresses = customers.Select(GetAddress);

What's the point of cluttering up your program with hundreds or thousands of four-line functions when you could just put the code you need where you need it as a short expression?

Second: lambdas close over local scopes

Which would you rather read, write and maintain, this:

var currentCity = GetCurrentCity();
var addresses = customers.Where(c=>c.City == currentCity).Select(c=>c.Address);

or:

static private Address GetAddress(Customer customer)
{
return customer.Address;
}

private class CityGetter
{
public string currentCity;
public bool DoesCityMatch(Customer customer)
{
return customer.City == this.currentCity;
}
}

....

var currentCityGetter = new CityGetter();
currentCityGetter.currentCity = GetCurrentCity();
var addresses = customers.Where(currentCityGetter.DoesCityMatch).Select(GetAddress);

All that vexing code is written for you when you use a lambda.

Third: Query comprehensions are rewritten to lambdas for you

When you write:

var addresses = from customer in customers
where customer.City == currentCity
select customer.Address;

it is transformed into the lambda syntax for you. Many people find this syntax pleasant to read, but we need the lambda syntax in order to actually make it work.

Fourth: lambdas are optionally type-inferred

Notice that we don't have to give the type of "customer" in the query comprehension above, or in the lambda versions, but we do have to give the type of the formal parameter when declaring it as a static method. The compiler is smart about inferring the type of a lambda parameter from context. This makes your code less redundant and more clear.

Fifth: Lambdas can become expression trees

Suppose you want to ask a web server "send me the addresses of the customers that live in the current city." Do you want to (1) pull down a million customers from the web site and do the filtering on your client machine, or (2) send the web site an object that tells it "the query contains a filter on the current city and then a selection of the address"? Let the server do the work and send you only the result that match.

Expression trees allow the compiler to turn the lambda into code that can be transformed into another query format at runtime and sent to a server for processing. Little helper methods that run on the client do not.

when should i use lambda expressions which comes with C# 3.0?

I don't think that there is a general rule when your should use them, but if I look to myself I tend to use them whenever I use anonymous methods. Most often this happens when spawning some code in a new thread using the ThreadPool, or when doing LINQ queries.

ThreadPool example:

ThreadPool.QueueUserWorkItem(state => {
// the code to run on separate thread goes here
});

LINQ:

var myItems = GetSomeIEnumerable()
.Where(o => o.SomeProperty.Equals("some value"));
.OrderBy(o => o.SomeOtherProperty);

Lambda Explanation and what it is as well as a good example

A lambda expression is used to create an anonymous function. Here an anonymous function is assigned to a delegate variable:

Func<int, int> increase = (a => a + 1);

You can then use the delegate to call the function:

var answer = increase(41);

Usually lambda expressions are used to send a delegate to a method, for example sending a delegate to the ForEach method so that it's called for each element in the list:

List<int> list = new List<int>();
list.Add(1);
list.Add(2);

list.ForEach(n => Console.WriteLine(n));

Understanding Lambda expressions and delegates

Delegates are methods that you can use as variables, like strings etc. For example you can declare a delegate method with one argument:

delegate void OneArgumentDelegate(string argument);

It doesn't do anything, much like an interface. If you have a method in any class with one argument like this:

void SomeMethod(string someArgument) {}

It matches the signature of the delegate, and thus can be assigned to a variable of its type:

OneArgumentDelegate ThisIsAVariable = new OneArgumentDelegate(SomeMethod);
OneArgumentDelegate ThisIsAlsoAVariable = SomeMethod; // Shorthand works too

These can then be passed as arguments to methods and invoked, like so:

void Main()
{
DoStuff(PrintString);
}

void PrintString(string text)
{
Console.WriteLine(text);
}

void DoStuff(OneArgumentDelegate action)
{
action("Hello!");
}

This will output Hello!.

Lambda expressions are a shorthand for the DoStuff(PrintString) so you don't have to create a method for every delegate variable you're going to use. You 'create' a temporary method that's passed on to the method. It works like this:

DoStuff(string text => Console.WriteLine(text)); // single line
DoStuff(string text => // multi line
{
Console.WriteLine(text);
Console.WriteLine(text);
});

Lambda expressions are just a shorthand, you might as well create a seperate method and pass it on. I hope you understand it better now ;-)



Related Topics



Leave a reply



Submit