60

Does anyone stick to any rules (or are you forced to stick to any rules by your employer?) when choosing to use either LINQ query syntax or a Lambda expression inside one of the LINQ extension methods? This applies to any Entities, SQL, objects, anything.

At our workplace, my boss doesn't like lambda at all and he'd use the query syntax for anything, which in some cases, I find are less readable.

var names = collection.Select(item => item.Name);

var names = from item in collection
            select item.Name;

Maybe when adding a condition, the Lambda I find gets a little messy, where the

var names = collection.Where(item => item.Name == "Fred")
                      .Select(item => item.Name);

var names = from item in collection
            where item.Name == "Fred"
            select item.Name;

Just out of interest: how does the compiler treat this one? Does anyone know how the above LINQ query will compile into lambda? Will the Name property be called for each element? Could we do this instead and potentially improve the performance? Would this mean lambda is slightly more controllable in terms of performance?

var names = collection.Select(item => item.Name)
                      .Where(name => name == "Fred");

Certainly when we start using more and more expressions, the lambda gets messy and I'd start to use the query syntax here.

var names = collection.Where(item => item.Name == "Fred")
                      .OrderBy(item => item.Age)
                      .Select(item => item.Name);

var names = from item in collection
            where item.Name == "Fred"
            order by item.Age
            select item.Name;

There are also a few things that I find can't be done with the query syntax. Some of them you'd think would be really simple (particularly aggregate functions), but no, you have to add one of the LINQ extension methods to the end, which imo, look neater with a lambda expression.

var names = collection.Count(item => item.Name == "Fred");

var names = (from item in collection
            where item.Name == "Fred"
            select item).Count()

Even for some of the simple lambda chains, ReSharper is suggesting I convert them to LINQ querys.

Can anyone else add to this? Does anyone have their own little rules or does their company suggest/force the use of one?

Connell
  • 13,925
  • 11
  • 59
  • 92

1 Answers1

42

To answer your question about translation, the query expression will always be translated based on the rules on 7.16 of the C# 4 spec (or the equivalent in the C# 3 spec). In the example where you're asking the question about the Name property, that's not a matter of the query expression translation - it's what the Select and Where methods do with the delegates or expression trees they take as parameters. Sometimes it makes sense to do a projection before filtering, sometimes not.

As for little rules, I only have one: use whichever way is most readable for the query in question. So if the query changes and "which form is more readable" changes at the same time, change the syntax used.

If you're going to use LINQ you should be happy with either syntax, at the very least to read.

I tend to find that queries with multiple range variable (e.g. via SelectMany or Join, or a let clause) end up being more readable using query expressions - but that's far from a hard and fast rule.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 4
    Also Query syntax doesn't offer all the operators. – MBen Nov 07 '11 at 14:20
  • Yup, that tends to be the rule I use. I know some people who basically tell me that "lambda is bad" and think I should always use the query syntax. – Connell Nov 07 '11 at 14:21
  • @ConnellWatkins: Well they clearly can't use all the operators in that case. See if they have any concrete reasons - I doubt that they have. – Jon Skeet Nov 07 '11 at 14:22
  • Also to comment on your update. I deliberately left out `Join` and `GroupBy` because they do look much more readable as a query. Also @Jon, do you have any comments on the *"Just out of interest"* bit in the 4th paragraph? – Connell Nov 07 '11 at 14:23
  • @JonSkeet well they say it's all about ugliness. I did think the `=>` looked ugly when I start on LINQ, but I'm used to it now. Not sure if I could think of a cleaner syntax that the C# team could've used. Maybe some kind of expression inference and a special keyword like the `value` keyword in a property setter would look nicer. – Connell Nov 07 '11 at 14:26
  • My team ran across a similar question locally and when we ran our comparisons (just with Linq to SQL) we found that the generated sql and the misl were identical even with small changes in the query structures. – Joel Etherton Nov 07 '11 at 14:28
  • 4
    @ConnellWatkins: I think the ugliness of having the "from where select" when you're *only* interested in applying a filter is much greater than the ugliness of the lambda - and what do they do if they want an overload which isn't supported? I've already addressed the "Just out of interest" bit - the compiler follows the language spec, it's as simple as that. – Jon Skeet Nov 07 '11 at 14:30
  • @Joel Ah, makes sense actually. I can sort of understand that with an IQueryable. But when using LINQ to Objects and just using an IEnumerable, that's just extension methods, which most likely contain a `foreach loop` and a `yield return`. – Connell Nov 07 '11 at 14:31
  • @ConnellWatkins: For a sample LINQ to Objects implementation, you might want to read my Edulinq series, which talks about various aspects of performance and implementation. – Jon Skeet Nov 07 '11 at 14:31
  • 2
    As usual, Jon beat me to the punch. I would have said the same thing: It depends. Prefer the syntax which is more maintainable for the given query. As for unsupported methods, I will point out that VB does have language support for more query expressions (Skip, Take, Distinct, Aggregate). One example I often see that I'll add: for a simple filter projecting a single item, I prefer `items.First(i => i.Prop == value)` over `(from i in items where i.Prop == value select i).First()` – Jim Wooley Nov 07 '11 at 17:02
  • 2
    When you start to chain Extension Methods together (especially the ones you write yourself) things look much nicer than combining the 2 syntax's. – DaveShaw Nov 07 '11 at 21:06
  • Particularly ones you write yourself? I never thought of doing that before! – Connell Nov 07 '11 at 23:43
  • 2
    @ConnellWatkins: Oh there are lots of possibilities - see http://morelinq.googlecode.com :) – Jon Skeet Nov 08 '11 at 06:17
  • 2
    I use method chain everywhere except for "join". – deerchao May 04 '13 at 17:49