LINQ – Lambda Expression vs Query Expression

Yan Cui

I help clients go faster for less using serverless technologies.

This article is brought to you by

I never fully recovered my workspace setup when I upgraded my laptop two years ago, and I still miss things today. If only I had known about Gitpod back then…

Learn more

As you’re probably aware of already, LINQ comes in two flavours – using Lambda expressions and using SQL-like query expressions:

Func<int, bool> isEven = i => i % 2 == 0;
int[] ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// using Query expression
var evensQuery = from i in ints where isEven(i) select i;
// using Lambda expression
var evensLambda = ints.Where(isEven);

Both yields the same result because query expressions are translated into their lambda expressions before they’re compiled. So performance-wise, there’s no difference whatsoever between the two.

Which one you should use is mostly personal preference, many people prefer lambda expressions because they’re shorter and more concise, but personally I prefer the query syntax having worked extensively with SQL. With that said, it’s important to bear in mind that there are situations where one will be better suited than the other.

Joins

Here’s an example of how you can join sequence together using Lambda and query expressions:

class Person
{
    public string Name { get; set; }
}
class Pet
{
    public string Name { get; set; }
    public Person Owner { get; set; }
}

void Main()
{
    var magnus = new Person { Name = "Hedlund, Magnus" };
    var terry = new Person { Name = "Adams, Terry" };
    var charlotte = new Person { Name = "Weiss, Charlotte" };
    var barley = new Pet { Name = "Barley", Owner = terry };
    var boots = new Pet { Name = "Boots", Owner = terry };
    var whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
    var daisy = new Pet { Name = "Daisy", Owner = magnus };
    var people = new List<Person> { magnus, terry, charlotte };
    var pets = new List<Pet> { barley, boots, whiskers, daisy };

    // using lambda expression
    var lambda = people.Join(pets,              // outer sequence
                             person => person,  // inner sequence key
                             pet => pet.Owner,  // outer sequence key
                             (person, pet) =>
                                 new { OwnerName = person.Name, Pet = pet.Name });

    // using query expression
    var query = from person in people
                join pet in pets on person equals pet.Owner
                select new { OwnerName = person.Name, Pet = pet.Name };
}

Again, both yields the same result and there is no performance penalties associated with either, but it’s easy to see why query syntax is far more readable and expressive of your intent here than the lambda expression!

Lambda-Only Functions

There are a number of methods that are only available with the Lambda expression, Single(), Take(), Skip(), First() just to name a few. Although you can mix and match the two by calling the Lambda-only methods at the end of the query:

// mix and match query and Lambda syntax
var query = (from person in people
             join pet in pets on person equals pet.Owner
             select new { OwnerName = person.Name, Pet = pet.Name }).Skip(1).Take(2);

As this reduces the readability of your code, it’s generally better to first assign the result of a query expression to a variable and then use Lambda expression using that variable:

var query = from person in people
            join pet in pets on person equals pet.Owner
            select new { OwnerName = person.Name, Pet = pet.Name };

var result = query.Skip(1).Take(2);

Both versions returns the same result because of delayed execution (the query is not executed against the underlying list until you try to iterate through the result variable). Also, because query expressions are translated to Lambda expressions first before being compiled there will not be performance penalties either. BUT, if you don’t want delayed execution, or need to use one of the aggregate functions such as Average() or Sum(), for example, you should be aware of the possibility of the underlying sequence being modified between the assignments to query and result. In this case,I’d argue it’s best to use Lambda expressions to start with or add the Lambda-only methods to the query expression.

Whenever you’re ready, here are 3 ways I can help you:

  1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
  2. I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
  3. Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.

7 thoughts on “LINQ – Lambda Expression vs Query Expression”

  1. How to convert this linq query into lambda expression.
    I’m using ASP.NET MVC (Visual Basic) – Visual Studio 2010.

    Dim query = From c In Me.ObjectContext.Customer
    Join uc In Me.ObjectContext.UserCostumer On c.CompanyID Equals uc.CompanyID And c.CustomerID Equals uc.CustomerID
    Where c.CompanyID = “AC” And uc.User = “admin”
    Select c

    HELP ME PLEASEEEEEEEEEE! :(

  2. theburningmonk

    Hi ReyPorto,

    Here’s how you might write this query in lambda:

    var customers = new List {
    new Customer { CompanyId = “AC”, CustomerId = “Customer1” },
    new Customer { CompanyId = “not-AC”, CustomerId = “Customer2” },
    };

    var userCustomers = new List {
    new UserCustomer { CompanyId = “AC”, CustomerId = “Customer1”, User = “not-admin” },
    new UserCustomer { CompanyId = “AC”, CustomerId = “Customer1”, User = “admin” },
    new UserCustomer { CompanyId = “AC”, CustomerId = “Customer2”, User = “not-admin” },
    new UserCustomer { CompanyId = “AC”, CustomerId = “Customer2”, User = “admin” },
    new UserCustomer { CompanyId = “not-AC”, CustomerId = “Customer1”, User = “not-admin” },
    new UserCustomer { CompanyId = “not-AC”, CustomerId = “Customer1”, User = “admin” },
    new UserCustomer { CompanyId = “not-AC”, CustomerId = “Customer2”, User = “not-admin” },
    new UserCustomer { CompanyId = “not-AC”, CustomerId = “Customer2”, User = “admin” }
    };

    // using query expression
    var query =
    from c in customers
    join uc in userCustomers on
    new { c.CompanyId, c.CustomerId } equals new { uc.CompanyId, uc.CustomerId }
    where c.CompanyId == “AC” && uc.User == “admin”
    select c;

    // using lambda expressions
    var lambda =
    customers
    .Where(c => c.CompanyId == “AC”) // inner sequence
    .Join(
    userCustomers.Where(uc => uc.User == “admin”), // outer sequence
    c => new { c.CompanyId, c.CustomerId }, // inner key selector
    uc => new { uc.CompanyId, uc.CustomerId }, // outer key selector
    (c, uc) => c);

    Both approach yields the same result (customer with company Id “AC” and customer Id “Customer1”), but as you can see, lambda expression is much harder to write and read!

    Hope this helps!

  3. OMG :O Thank u very much!!!!!! The result is the same…
    THANKSSSS!!!!! Blessings!!!! =)
    =)
    =)

  4. thank you. i was just coding lambda expressions and linq and didn’t have a clear idea about the difference other than the syntax.

  5. Pingback: Even more powerful LINQ debugging, now with Query Syntax support! – The OzCode Blog

Leave a Comment

Your email address will not be published. Required fields are marked *