Dataslope logoDataslope

Query vs Method Syntax

The two faces of LINQ — when SQL-like query syntax shines, when fluent method chains win, and how the compiler bridges them

C# offers two syntactic styles for writing LINQ. They look very different, but they compile to the same code and have identical semantics. Choosing between them is a matter of readability.

This page builds an intuition for when each style serves you best — and shows you what the compiler does behind the scenes so the two never feel like separate languages.

A side-by-side tour

The same query, three ways.

Code Block
C# 13

All three produce the same result. The compiler treats query syntax as syntactic sugar: it mechanically rewrites it into method calls.

The translation rules

Every query clause has a 1-to-1 method counterpart.

Query clauseMethod call
from x in xs(source)
from y in ys (second from)SelectMany
where pWhere(x => p)
select eSelect(x => e)
orderby k, orderby k descendingOrderBy / OrderByDescending
orderby k1, k2OrderBy(k1).ThenBy(k2)
group e by kGroupBy(x => k, x => e)
join y in ys on a equals bJoin
let v = eSelect into anonymous type
into g (after group/join)continues the chain

Knowing the translation lets you read either dialect fluently.

When query syntax reads better

Query syntax really earns its keep in three scenarios.

1. Multiple from clauses (cross-product / flattening)

var pairs =
    from x in xs
    from y in ys
    where x + y == 10
    select (x, y);

The method-syntax equivalent uses SelectMany with two lambdas and is genuinely harder to read:

var pairs = xs.SelectMany(x => ys, (x, y) => (x, y))
              .Where(t => t.x + t.y == 10);

2. let bindings

let introduces a named intermediate value visible in the rest of the query.

Code Block
C# 13

In method syntax, you'd need a tuple projection just to carry len through the pipeline.

3. join clauses

var labeled =
    from order in orders
    join cust in customers on order.CustomerId equals cust.Id
    select new { order.Id, cust.Name, order.Total };

Join in method form requires four lambdas and a key selector dance. Query syntax keeps it visually flat — much closer to SQL.

When method syntax reads better

Method syntax wins almost everywhere else, particularly when the query is mostly transformation and aggregation.

// method: short and clear
var topRevenue = orders
    .Where(o => o.Status == "completed")
    .Sum(o => o.Total);

// query equivalent is awkward — query syntax cannot end with Sum
var topRevenue2 = (
    from o in orders
    where o.Status == "completed"
    select o.Total
).Sum();

Method syntax also wins when you need operators that have no query keyword: Take, Skip, Distinct, Count, First, Aggregate, Zip, Concat, Reverse, Chunk, and many more.

What the compiler actually does

Let's see a non-trivial example translated by hand.

// query
var q =
    from c in customers
    from o in c.Orders
    where o.Total > 100
    let tax = o.Total * 0.08m
    orderby c.Name
    select new { c.Name, o.Id, tax };

The compiler rewrites this in stages:

  1. Two froms → SelectMany with a "carry" tuple.
  2. whereWhere.
  3. letSelect that adds tax to the carry.
  4. orderbyOrderBy.
  5. Final selectSelect projecting only the wanted fields.

The result is a long, deeply-nested method chain. Nobody writes that by hand. Which is exactly the point: query syntax is the ergonomics layer on top.

Practice: rewrite both ways

Challenge
C# 13

Both pipelines should now produce the same single line — Knuth: 2150 — because Knuth's three volumes (650 + 700 + 800 = 2150) are the only author group whose total page count exceeds the 1500 threshold.

A guiding heuristic

If your query has multiple sequences, let, or join, reach for query syntax. Otherwise, prefer method syntax.

There is no winner. They are the same LINQ. Pick whichever makes the reader understand the intent fastest.

QuestionSelect one

Which statement about query vs. method syntax is correct?

Query syntax can express things method syntax cannot.

Method syntax is faster at runtime because it skips the compiler rewrite step.

Query syntax always reads better when more than one operator is involved.

They compile to identical method calls; the choice between them is purely about readability.

On this page