C# & .NET (C# 14, .NET 10 LTS) Module 14
LINQ interview questions
Interview questions on LINQ: short warm-ups, then what each harder question tests, the first step of a good answer and its follow-ups.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
What is the difference between First, FirstOrDefault and Single in LINQ?
-
Fresher
What is the difference between Select and SelectMany?
Answered in the lesson LINQ projection, filtering, sorting and paging
-
Fresher
What is the difference between GroupBy and ToLookup?
-
Fresher
What is the difference between Join and GroupJoin?
Answered in the lesson LINQ joins: Join, GroupJoin, LeftJoin and RightJoin
-
Fresher
What is the difference between IEnumerable and IQueryable in C#?
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to mid
A checkout looks up the customer with customers.Single(c => c.Email == email). Since a bulk import, it throws "Sequence contains more than one matching element" for a few users. What does the error tell you, and what do you change, in the code and in the data?
- What it tests
- What Single promises, reading a LINQ exception as evidence about the data, and fixing the rule that let duplicates in rather than hiding them with First.
- First step
- Read the message as a finding about the data, not a bug in the query: two customers share one email. Before you touch the code, count the emails that now occur more than once, and ask whether an email was meant to be unique.
- Follow-ups
-
- Why is replacing Single with First the wrong first fix?
- How would you list every duplicated email with LINQ?
- Where should uniqueness be enforced so the import cannot break it again?
From the lesson LINQ: your first queries
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A service builds var overdue = invoices.Where(i => i.Due < today) once at start-up, where today is a local, and reads overdue on every request. New invoices show up in it, yet after midnight the invoices due the day before are still missing. Explain both behaviours and fix the code.
- What it tests
- Deferred execution, what a lambda captures, and deciding what a long-lived service computes per request and what it may keep.
- First step
- Separate the two things the query holds. The source, invoices, is read again on every enumeration, which is why new invoices appear. today is a variable captured when the service started and never assigned again, so the cut-off date is frozen at start-up.
- Follow-ups
-
- Would calling ToList() at start-up fix it?
- How would you make the date testable?
- What can go wrong if another thread adds invoices while a request reads the query?
From the lesson LINQ: your first queries
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A sales report sorts orders with .OrderBy(o => o.Region).OrderBy(o => o.Date). Users say the regions are mixed together, although within one date the regions look sorted. Explain exactly what the query does, fix it, and say how a test would have caught it.
- What it tests
- How OrderBy and ThenBy combine, why the result looks almost right, and test data for an order with ties.
- First step
- Read the second OrderBy as a new sort, not as a second key: it sorts every order by date. Then work out what decides the order of two orders that share a date, and compare that with what the users see.
- Follow-ups
-
- Why does the report look right for some dates?
- How would you write the fix in query syntax?
- What test data would expose the bug?
From the lesson LINQ projection, filtering, sorting and paging
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
An export merges two CSV files into a List<Customer> and calls Distinct() on it, but the duplicate customers stay. Customer is a class. Explain why, and compare three ways to remove the duplicates.
- What it tests
- How Distinct decides that two items are the same, reference against value equality, and choosing between a record, DistinctBy and a comparer.
- First step
- Ask what Distinct compares. It calls Equals and GetHashCode, and for a class that does not override them they compare references: every object built from a CSV row is a different object, even when all its values match another row's.
- Follow-ups
-
- Which copy does DistinctBy keep, and how do you control it?
- What else changes if Customer becomes a record?
- How do you treat emails that differ only in case as the same customer?
From the lesson LINQ projection, filtering, sorting and paging
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A feed loads 20 posts a page with posts.OrderByDescending(p => p.CreatedAt).Skip(page * 20).Take(20). In busy hours users see the same post twice while scrolling, and now and then a post never appears. Explain both and redesign the paging.
- What it tests
- Offset against keyset paging, what moves an offset page while a user scrolls, and a sort key that is unique and stable.
- First step
- Write down what Skip(page * 20) counts: positions, not posts. Then replay two page requests on paper, once with a post published between them and once with a post deleted, and note which post each second page starts with.
- Follow-ups
-
- Why is CreatedAt alone not a good page key?
- What does the app send to ask for the next page?
- When is offset paging still the right choice?
From the lesson LINQ projection, filtering, sorting and paging
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A dashboard shows each store's average sale with stores.Select(s => new { s.Name, Avg = s.Sales.Average(x => x.Amount) }). The morning a new store opens, the whole page fails with InvalidOperationException. Explain the cause, fix it, and say what the page should show for that store.
- What it tests
- What the aggregates do with an empty sequence, the nullable overloads and DefaultIfEmpty, and choosing an honest value to show.
- First step
- Find the store whose Sales is empty. Average has no value to return for it, so it throws, and because the page reads the query as a whole, one empty store breaks every row.
- Follow-ups
-
- Why is DefaultIfEmpty(0) the wrong fix here?
- What do Sum and Count return for the same store?
- How would a test catch this before the store opens?
From the lesson LINQ grouping and aggregation
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A support report groups the month's tickets with tickets.GroupBy(t => t.Status) and prints a count per status. In quiet months the Escalated row disappears instead of showing 0, and the chart built on it shifts its colours. Explain why and fix it.
- What it tests
- That grouping finds only the keys present in the data, deciding which rows a report must show, and a count of 0 for a key with no items.
- First step
- Notice where the rows come from: GroupBy makes a group only for a status that occurs in the tickets, so a month without escalations has no Escalated group.
- Follow-ups
-
- How does ToLookup make the fix short?
- Would CountBy fix it on its own?
- How do you keep the statuses in a fixed order for the chart?
From the lesson LINQ grouping and aggregation
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A nightly job reads 50 million log lines lazily, groups them with GroupBy(l => l.StatusCode) and counts each group. It fails with OutOfMemoryException. What does GroupBy keep, roughly how much memory is that, and what do you use instead?
- What it tests
- What GroupBy holds in memory, estimating it from measured numbers, and CountBy, AggregateBy or a dictionary as the fix.
- First step
- List what GroupBy must keep: every line, in its group, until the last line has been read, because it hands on no group before then. Counting needs one number per status code, not the lines.
- Follow-ups
-
- Why do the lines themselves matter more than the references to them?
- What would ToLookup change?
- How do you count by status code and hour together the same way?
From the lesson LINQ grouping and aggregation
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A revenue report joins customers to orders with Join and counts the customers in the result. The count is 1,200 lower than the CRM's, and finance asks which customers are missing. Explain the gap and write the query that lists them.
- What it tests
- Inner join semantics, keeping unmatched rows with LeftJoin, and counting distinct customers rather than joined rows.
- First step
- An inner join keeps only customers with at least one matching order, so customers without orders in the period vanish from it. Then notice that the joined rows are orders, not customers, so counting them answers another question.
- Follow-ups
-
- Why does counting the rows of the join give a wrong number of customers as well?
- How do you list the missing customers in one query?
- What else can make customers fall out of a join?
From the lesson LINQ joins: Join, GroupJoin, LeftJoin and RightJoin
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A nightly job matches 200,000 payments to 200,000 invoices with payments.Select(p => (p, invoices.First(i => i.Number == p.InvoiceNumber))). It now takes hours and sometimes throws. Explain both, estimate the work, and rewrite it.
- What it tests
- The cost of a search inside a loop, estimating comparisons, Join or a dictionary as the fix, and what First does with a missing match.
- First step
- Count the comparisons. First scans the invoices from the start for every payment: about half the list on average when the invoice exists, all of it when it does not. That is billions of comparisons, and a payment whose invoice is missing makes First throw.
- Follow-ups
-
- How do LeftJoin or a dictionary handle a payment whose invoice is missing?
- How many comparisons does a Join need for the same data?
- When is a dictionary better than Join here?
From the lesson LINQ joins: Join, GroupJoin, LeftJoin and RightJoin
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
Two exports, train runs and platform allotments, are joined on new { Station, Day }. Half the runs find no platform, although every pair looks present when you read the two files. What do you check, in what order, and how do you fix the join?
- What it tests
- Composite key equality, case and spaces in keys, normalising keys, and using a left join to find the rows that fail.
- First step
- Find the failing rows first: LeftJoin on the same key and keep the runs whose platform is null. Then compare their keys with the platforms' keys character by character: case, spaces at the ends, and spellings such as "Mon" against "Monday".
- Follow-ups
-
- Why can a string comparer not be passed straight to a join on an anonymous-type key?
- How do you normalise keys without changing the values you show?
- How do you stop the next export from breaking the join again?
From the lesson LINQ joins: Join, GroupJoin, LeftJoin and RightJoin
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
An endpoint returns db.Customers.AsEnumerable().Where(c => c.City == city).Take(20).ToList() through EF Core. It was fast in testing; in production each request takes seconds, and the database sends every customer. Explain what runs where, and fix it without changing the result.
- What it tests
- IQueryable against IEnumerable operators, what AsEnumerable does to the rest of a query, and reading the SQL that a provider sends.
- First step
- Find where the query leaves the tree. Everything before AsEnumerable() is translated, and that is only the table, so the database sends every customer; Where and Take then run in the web server, on rows it had to receive and build first.
- Follow-ups
-
- Why was it fast in testing?
- How do you see the SQL that EF Core sends?
- When is AsEnumerable() the right call?
From the lesson IQueryable and expression trees
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
An admin search page builds an Expression<Func<Order, bool>> from query-string fields such as field=Total, op=gt and value=500, passing the field name straight to Expression.Property. Review the design: what can go wrong, how do you build the tree safely, and how do you test it?
- What it tests
- Treating names from a request as input, allowlists, constants of the field's own type, refusing bad criteria when the filter is built, and testing a builder rule by rule.
- First step
- List what the request controls: a property name, an operator and a value. Each can be wrong or hostile, so each needs a rule: an allowlist of fields, a fixed set of operators, and a value parsed into the field's own type.
- Follow-ups
-
- Why is a denylist of sensitive fields not enough?
- What happens if the value reaches a numeric field as a string?
- How would you avoid compiling the same filter again and again?
From the lesson IQueryable and expression trees
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A repository's unit tests pass against a list wrapped with AsQueryable(), but in production the same query throws when it is read, because the database provider cannot translate one predicate. Why do the tests miss it, and how do you test queries so they would not?
- What it tests
- That AsQueryable() over a list runs any tree in memory while a real provider translates only what it knows, and testing queries against the real provider.
- First step
- Compare what runs the tree in each place. Over a list, the predicate runs as compiled C#, so a call to any method works. The database provider must turn every node into SQL, and it refuses a method it does not know, when the query is read.
- Follow-ups
-
- Which predicates are most likely to differ between the two?
- What would you run in CI instead?
- Can a compiler upgrade change a predicate that used to translate?
From the lesson IQueryable and expression trees
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
All C# & .NET (C# 14, .NET 10 LTS) interview questions · The C# & .NET (C# 14, .NET 10 LTS) track