[{"data":1,"prerenderedAt":115},["ShallowReactive",2],{"qa-\u002Fdotnet\u002Ffundamentals\u002Flinq":3},{"page":4,"siblings":95,"blog":112},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":85,"related":86,"seo":87,"seoDescription":88,"stem":89,"subtopic":90,"topic":91,"topicSlug":92,"updated":93,"__hash__":94},"qa\u002Fdotnet\u002Ffundamentals\u002Flinq.md","Linq",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md",".NET Core","dotnet",{},true,4,"\u002Fdotnet\u002Ffundamentals\u002Flinq",[23,28,32,36,40,44,48,52,56,60,64,69,73,77,81],{"id":24,"difficulty":25,"q":26,"a":27},"what-is-linq","easy","What is LINQ and what problem does it solve?","**Language Integrated Query (LINQ)** is a set of C# language features and BCL\nextension methods that let you query any data source — collections, XML, databases,\nJSON — using a uniform, type-safe syntax directly in C# code.\n\n```csharp\nint[] numbers = { 5, 3, 8, 1, 9, 2 };\n\n\u002F\u002F Without LINQ: imperative loop\nvar evens = new List\u003Cint>();\nforeach (var n in numbers)\n    if (n % 2 == 0) evens.Add(n);\n\n\u002F\u002F With LINQ method syntax:\nvar evensLinq = numbers.Where(n => n % 2 == 0)\n                       .OrderBy(n => n)\n                       .ToList();  \u002F\u002F [2, 8]\n\n\u002F\u002F Query syntax (translates to the same method calls):\nvar evensQuery = (from n in numbers\n                  where n % 2 == 0\n                  orderby n\n                  select n).ToList();\n```\n\nLINQ is not limited to in-memory collections. The same syntax works for SQL\ndatabases via Entity Framework (`IQueryable\u003CT>`), XML via LINQ to XML, and any\ncustom data source that implements `IEnumerable\u003CT>` or `IQueryable\u003CT>`.\n\n**Rule of thumb:** LINQ makes collection operations declarative and composable —\nyou describe *what* you want, not *how* to iterate. Prefer it over imperative\nloops for readability; fall back to `foreach` only when performance profiling\njustifies it.\n",{"id":29,"difficulty":14,"q":30,"a":31},"deferred-execution","What is deferred execution in LINQ and why does it matter?","**Deferred execution** means a LINQ query is not evaluated when it is defined —\nit is evaluated only when you iterate the result. Each iteration re-runs the query\nagainst the current state of the source.\n\n```csharp\nvar numbers = new List\u003Cint> { 1, 2, 3, 4, 5 };\n\n\u002F\u002F This builds a query object — no iteration yet:\nvar query = numbers.Where(n => n > 2); \u002F\u002F deferred\n\nnumbers.Add(10); \u002F\u002F modify source after query is defined\n\nforeach (var n in query) Console.Write(n + \" \"); \u002F\u002F 3 4 5 10 — sees the new item!\n\n\u002F\u002F Force immediate execution with ToList() \u002F ToArray() \u002F Count():\nvar snapshot = numbers.Where(n => n > 2).ToList(); \u002F\u002F evaluated NOW\nnumbers.Add(99);\n\u002F\u002F 'snapshot' still contains { 3, 4, 5, 10 } — not affected by later changes\n```\n\nDeferred execution enables **query composition** — you can build a query\nincrementally and it only hits the data source once when iterated. The danger is\n**multiple enumeration**: iterating a deferred query twice runs it twice. Pass\na `IEnumerable\u003CT>` to a method that iterates it twice and you pay double the cost.\n\n**Rule of thumb:** Call `.ToList()` or `.ToArray()` to materialise when you will\niterate multiple times, need a point-in-time snapshot, or want to avoid re-querying\na database in EF Core.\n",{"id":33,"difficulty":25,"q":34,"a":35},"query-vs-method-syntax","What is the difference between LINQ query syntax and method syntax?","Both syntaxes produce identical IL — the compiler translates query syntax into\nmethod calls. Query syntax is SQL-like; method syntax (fluent) uses extension\nmethods chained with lambdas.\n\n```csharp\nvar data = new[] { 1, 2, 3, 4, 5, 6 };\n\n\u002F\u002F Query syntax:\nvar q1 = from n in data\n         where n % 2 == 0\n         orderby n descending\n         select n * n;\n\n\u002F\u002F Method (fluent) syntax — identical result:\nvar q2 = data.Where(n => n % 2 == 0)\n             .OrderByDescending(n => n)\n             .Select(n => n * n);\n\n\u002F\u002F Some operators only exist in method syntax (no query-syntax equivalent):\nvar q3 = data.Zip(data.Reverse(), (a, b) => a + b); \u002F\u002F Zip has no query syntax\nvar q4 = data.Aggregate((acc, n) => acc + n);        \u002F\u002F Aggregate has no query syntax\nvar count = data.Count(n => n > 3);                  \u002F\u002F Count with predicate — method only\n```\n\n**Method syntax** is more common in practice because it composes naturally with\nmethod chaining and covers more operators. **Query syntax** reads more naturally\nfor complex multi-source joins, let clauses, and group-by queries.\n\n**Rule of thumb:** Default to method syntax — it covers every operator and is\nwhat most .NET codebases use. Switch to query syntax for complex joins or when\nthe `let` keyword (intermediate variable) would significantly aid readability.\n",{"id":37,"difficulty":14,"q":38,"a":39},"ienumerable-vs-iqueryable","What is the difference between `IEnumerable\u003CT>` and `IQueryable\u003CT>` in LINQ?","`IEnumerable\u003CT>` executes LINQ in **memory** (LINQ to Objects). `IQueryable\u003CT>`\n**translates** the LINQ expression tree into the query language of the data source\n(typically SQL) and executes it there.\n\n```csharp\n\u002F\u002F IEnumerable: filtering happens in C# after loading ALL rows from DB\nIEnumerable\u003CUser> usersEnum = dbContext.Users.ToList(); \u002F\u002F loads ALL users first\nvar active = usersEnum.Where(u => u.IsActive); \u002F\u002F filters in memory — bad!\n\n\u002F\u002F IQueryable: filtering is translated to SQL — only matching rows are fetched\nIQueryable\u003CUser> usersQuery = dbContext.Users;  \u002F\u002F no DB hit yet\nvar activeQ = usersQuery.Where(u => u.IsActive); \u002F\u002F adds WHERE to SQL expression\nvar result = activeQ.ToList(); \u002F\u002F ONE SQL: SELECT * FROM Users WHERE IsActive = 1\n```\n\n`IQueryable\u003CT>` stores an **expression tree** — a data structure representing the\nquery. When you call `ToList()`, the LINQ provider (EF Core, LINQ to SQL) walks\nthe expression tree and generates the appropriate query. `IEnumerable\u003CT>` just\nholds a delegate — it has no visibility into what the lambda does and cannot\ntranslate it.\n\n**Rule of thumb:** Use `IQueryable\u003CT>` for database queries so filtering, sorting,\nand pagination happen in SQL. Convert to `IEnumerable\u003CT>` (`.AsEnumerable()`) only\nwhen you need to run logic the provider cannot translate.\n",{"id":41,"difficulty":14,"q":42,"a":43},"select-vs-selectmany","What is the difference between `Select` and `SelectMany` in LINQ?","`Select` projects each element to one output element (1-to-1). `SelectMany`\nprojects each element to a **sequence** and flattens all those sequences into a\nsingle output sequence (1-to-many → flat).\n\n```csharp\nvar orders = new[]\n{\n    new { Id = 1, Items = new[] { \"pen\", \"book\" } },\n    new { Id = 2, Items = new[] { \"desk\", \"chair\", \"lamp\" } },\n};\n\n\u002F\u002F Select — returns IEnumerable\u003Cstring[]>: each order maps to its array\nvar nested = orders.Select(o => o.Items);\n\u002F\u002F Result: [ [\"pen\",\"book\"], [\"desk\",\"chair\",\"lamp\"] ]\n\n\u002F\u002F SelectMany — flattens into IEnumerable\u003Cstring>\nvar flat = orders.SelectMany(o => o.Items);\n\u002F\u002F Result: [\"pen\", \"book\", \"desk\", \"chair\", \"lamp\"]\n\n\u002F\u002F Common use: get all characters in all words:\nvar words = new[] { \"hello\", \"world\" };\nvar chars = words.SelectMany(w => w.ToCharArray()).Distinct().OrderBy(c => c);\n\u002F\u002F d e h l o r w\n```\n\n`SelectMany` is equivalent to a nested `foreach` that adds each inner element to a\nflat output list. In query syntax, it corresponds to multiple `from` clauses.\n\n**Rule of thumb:** If each source element maps to a collection and you want a\nflat result, use `SelectMany`. If you want a sequence of sequences (or one-to-one),\nuse `Select`.\n",{"id":45,"difficulty":25,"q":46,"a":47},"first-single-default","What is the difference between `First()`, `FirstOrDefault()`, `Single()`, and `SingleOrDefault()`?","These four methods differ on **how many elements are expected** and **what happens\nwhen the expectation is violated**.\n\n```csharp\nvar empty = Array.Empty\u003Cint>();\nvar one   = new[] { 42 };\nvar multi = new[] { 1, 2, 3 };\n\n\u002F\u002F First() — expects at least one; throws if empty\nmulti.First();            \u002F\u002F 1\nmulti.First(n => n > 1);  \u002F\u002F 2\n\u002F\u002F empty.First();         \u002F\u002F InvalidOperationException!\n\n\u002F\u002F FirstOrDefault() — returns default(T) if empty, no throw\nempty.FirstOrDefault();   \u002F\u002F 0 (default int)\nempty.FirstOrDefault(-1); \u002F\u002F -1 (C# 10 default value param)\n\n\u002F\u002F Single() — expects exactly one; throws if empty OR if more than one\none.Single();             \u002F\u002F 42\n\u002F\u002F multi.Single();        \u002F\u002F InvalidOperationException — more than one element!\n\u002F\u002F empty.Single();        \u002F\u002F InvalidOperationException — sequence is empty!\n\n\u002F\u002F SingleOrDefault() — returns default if empty; throws if more than one\none.SingleOrDefault();    \u002F\u002F 42\nempty.SingleOrDefault();  \u002F\u002F 0 — fine\n\u002F\u002F multi.SingleOrDefault(); \u002F\u002F InvalidOperationException — still throws for multiple!\n```\n\n**Rule of thumb:** Use `First`\u002F`FirstOrDefault` when you expect a list and want the\nfirst match. Use `Single`\u002F`SingleOrDefault` when exactly one result is a business\nrequirement (e.g., look up by unique ID) — the exception is a useful assertion.\n",{"id":49,"difficulty":14,"q":50,"a":51},"groupby","How does `GroupBy` work in LINQ?","`GroupBy` partitions elements into groups based on a key. It returns\n`IEnumerable\u003CIGrouping\u003CTKey, TElement>>` — each group has a `Key` property and\nis itself an `IEnumerable\u003CTElement>`.\n\n```csharp\nvar products = new[]\n{\n    new { Name = \"Pen\",   Category = \"Stationery\", Price = 1.5  },\n    new { Name = \"Book\",  Category = \"Education\",  Price = 12.0 },\n    new { Name = \"Ruler\", Category = \"Stationery\", Price = 0.8  },\n    new { Name = \"Calc\",  Category = \"Education\",  Price = 25.0 },\n};\n\nvar byCategory = products.GroupBy(p => p.Category);\n\nforeach (var group in byCategory)\n{\n    Console.WriteLine($\"{group.Key}: {group.Count()} items, \" +\n                      $\"avg £{group.Average(p => p.Price):F2}\");\n}\n\u002F\u002F Stationery: 2 items, avg £1.15\n\u002F\u002F Education:  2 items, avg £18.50\n\n\u002F\u002F With element projection:\nvar namesByCategory = products\n    .GroupBy(p => p.Category, p => p.Name)\n    .ToDictionary(g => g.Key, g => g.ToList());\n\u002F\u002F { \"Stationery\": [\"Pen\",\"Ruler\"], \"Education\": [\"Book\",\"Calc\"] }\n```\n\nIn EF Core, `GroupBy` on `IQueryable\u003CT>` translates to SQL `GROUP BY`. However,\nnot all LINQ `GroupBy` projections can be translated — EF Core will throw at runtime\nif it cannot. Use `.AsEnumerable()` before `GroupBy` to force in-memory grouping\nwhen needed.\n\n**Rule of thumb:** `GroupBy` is for aggregating by a category. Always follow it\nwith `Count()`, `Sum()`, `Average()`, `Max()`, or a materialising call — iterating\nan `IGrouping` multiple times re-evaluates the source.\n",{"id":53,"difficulty":25,"q":54,"a":55},"any-all-count","When do you use `Any()`, `All()`, and `Count()` in LINQ?","These three check membership or quantity. Knowing which to use avoids common\nperformance mistakes.\n\n```csharp\nvar nums = new[] { 1, 2, 3, 4, 5 };\n\n\u002F\u002F Any() — \"does at least one element satisfy the condition?\"\nnums.Any();              \u002F\u002F true (sequence is non-empty)\nnums.Any(n => n > 10);  \u002F\u002F false\n\n\u002F\u002F All() — \"do ALL elements satisfy the condition?\"\nnums.All(n => n > 0);   \u002F\u002F true\nnums.All(n => n > 3);   \u002F\u002F false\n\n\u002F\u002F Count() — how many satisfy the condition?\nnums.Count();            \u002F\u002F 5\nnums.Count(n => n > 3); \u002F\u002F 2 (4 and 5)\n\n\u002F\u002F COMMON MISTAKE — avoid:\nif (list.Count() > 0) { }   \u002F\u002F iterates entire list to count\n\u002F\u002F Prefer:\nif (list.Any()) { }         \u002F\u002F stops at first element — O(1) for List\u003CT>\n```\n\nFor `ICollection\u003CT>` (like `List\u003CT>`), `.Count` (property, not method) is O(1).\nThe `Count()` extension method iterates when the source is not an `ICollection\u003CT>`.\nIn EF Core, both translate to `SELECT COUNT(*)` in SQL, so the difference is moot\nthere — but `Any()` translates to `EXISTS (SELECT 1 ...)` which can be faster.\n\n**Rule of thumb:** Use `Any()` to check emptiness or existence. Use `Count()` only\nwhen you need the actual number. Never call `Count() > 0` — use `Any()` instead.\n",{"id":57,"difficulty":14,"q":58,"a":59},"aggregate","What is `Aggregate()` in LINQ and what is it equivalent to in functional programming?","`Aggregate()` is LINQ's **fold** (also called `reduce`). It accumulates a sequence\ninto a single value by repeatedly applying a function to a running accumulator and\nthe next element.\n\n```csharp\nvar nums = new[] { 1, 2, 3, 4, 5 };\n\n\u002F\u002F Sum via Aggregate (seed defaults to first element):\nint sum = nums.Aggregate((acc, n) => acc + n); \u002F\u002F 15\n\n\u002F\u002F With explicit seed:\nint product = nums.Aggregate(1, (acc, n) => acc * n); \u002F\u002F 120\n\n\u002F\u002F With result selector (seed, fold, then transform):\nstring csv = nums.Aggregate(\n    new System.Text.StringBuilder(),\n    (sb, n) => { sb.Append(n).Append(','); return sb; },\n    sb => sb.ToString().TrimEnd(',')\n); \u002F\u002F \"1,2,3,4,5\"\n\n\u002F\u002F String joining (Aggregate style vs string.Join):\nstring joined = new[] { \"a\", \"b\", \"c\" }.Aggregate((a, b) => $\"{a},{b}\"); \u002F\u002F \"a,b,c\"\n\u002F\u002F Prefer: string.Join(\",\", new[] { \"a\",\"b\",\"c\" }) — more readable + efficient\n```\n\n`Aggregate` is the most general LINQ operator — `Sum`, `Max`, `Min`, `Count`, and\n`Average` are all special cases of `Aggregate`. Use the specialised versions when\nthey exist; reach for `Aggregate` only when none of the purpose-built operators fit.\n\n**Rule of thumb:** `Aggregate` = fold\u002Freduce. Use named operators (`Sum`, `Max`)\nwhen they exist. Use `Aggregate` for custom fold logic like building a running\nproduct, combining strings with separators, or computing complex rolling statistics.\n",{"id":61,"difficulty":14,"q":62,"a":63},"tolist-vs-asenumerable","What is the difference between `ToList()`, `ToArray()`, and `AsEnumerable()`?","`ToList()` and `ToArray()` both **materialise** a LINQ query into a concrete\nin-memory collection, forcing immediate execution. `AsEnumerable()` keeps the\nquery deferred but switches the compile-time type from `IQueryable\u003CT>` to\n`IEnumerable\u003CT>`, causing subsequent operators to run in memory.\n\n```csharp\nIQueryable\u003CUser> query = dbContext.Users.Where(u => u.IsActive);\n\n\u002F\u002F ToList() — executes SQL NOW, returns List\u003CUser>\nList\u003CUser> list = query.ToList();\n\n\u002F\u002F ToArray() — executes SQL NOW, returns User[]\nUser[] array = query.ToArray();\n\n\u002F\u002F AsEnumerable() — no execution yet; shifts to LINQ-to-Objects for subsequent ops\nIEnumerable\u003CUser> enumerable = query.AsEnumerable();\n\u002F\u002F The next Where runs in C# memory, not SQL:\nvar localFilter = enumerable.Where(u => MyComplexCSharpMethod(u));\n\u002F\u002F When you iterate 'localFilter', it fetches ALL active users from DB first, then filters\n```\n\nUse `AsEnumerable()` when a LINQ provider (EF Core) cannot translate a particular\noperator or lambda to SQL — it forces the remainder of the pipeline to run in\nmemory on the already-fetched rows.\n\n**Rule of thumb:** `ToList()` or `ToArray()` = execute now + store. `AsEnumerable()`\n= switch to in-memory LINQ without executing yet (the DB query still fires when you\niterate). Choose `ToList()` for most cases; `ToArray()` when you need a fixed-size buffer.\n",{"id":65,"difficulty":66,"q":67,"a":68},"linq-join","hard","How does a LINQ join work, and what is the difference between `Join` and `GroupJoin`?","`Join` produces a flat sequence where each left element is matched with each right\nelement on a key — equivalent to SQL `INNER JOIN`. `GroupJoin` produces a\nhierarchical result — each left element paired with all its matching right elements\n— equivalent to SQL `LEFT OUTER JOIN` (when combined with `DefaultIfEmpty`).\n\n```csharp\nvar customers = new[] {\n    new { Id = 1, Name = \"Alice\" },\n    new { Id = 2, Name = \"Bob\"   },\n};\nvar orders = new[] {\n    new { CustomerId = 1, Item = \"Book\"  },\n    new { CustomerId = 1, Item = \"Pen\"   },\n    new { CustomerId = 2, Item = \"Desk\"  },\n};\n\n\u002F\u002F Join — flat INNER JOIN:\nvar inner = customers.Join(orders,\n    c => c.Id,          \u002F\u002F outer key\n    o => o.CustomerId,  \u002F\u002F inner key\n    (c, o) => $\"{c.Name}: {o.Item}\");\n\u002F\u002F Alice: Book, Alice: Pen, Bob: Desk\n\n\u002F\u002F GroupJoin — hierarchical LEFT JOIN:\nvar grouped = customers.GroupJoin(orders,\n    c => c.Id,\n    o => o.CustomerId,\n    (c, orderGroup) => new { c.Name, Orders = orderGroup.ToList() });\n\u002F\u002F { Name=\"Alice\", Orders=[Book,Pen] }, { Name=\"Bob\", Orders=[Desk] }\n```\n\nIn EF Core on `IQueryable`, `Join` translates to SQL `INNER JOIN` and `GroupJoin`\ntranslates to `LEFT JOIN` (when `.SelectMany(..., DefaultIfEmpty())` is applied).\n\n**Rule of thumb:** Use `Join` for inner joins (only matching records). Use\n`GroupJoin` when you need a parent with a collection of children, or when you\nwant to preserve left-side records even if there are no matches.\n",{"id":70,"difficulty":14,"q":71,"a":72},"zip","What is `Zip()` in LINQ and when would you use it?","`Zip` merges two (or three, since .NET 6) sequences element-by-element, producing\none output element per pair. It stops when the shorter sequence is exhausted.\n\n```csharp\nvar names  = new[] { \"Alice\", \"Bob\", \"Charlie\" };\nvar scores = new[] { 92, 85, 78 };\n\n\u002F\u002F Two-sequence Zip with result selector:\nvar results = names.Zip(scores, (name, score) => $\"{name}: {score}\");\n\u002F\u002F [\"Alice: 92\", \"Bob: 85\", \"Charlie: 78\"]\n\n\u002F\u002F C# 6+: Zip returning tuples (no selector needed):\nvar pairs = names.Zip(scores); \u002F\u002F IEnumerable\u003C(string, int)>\nforeach (var (name, score) in pairs)\n    Console.WriteLine($\"{name} scored {score}\");\n\n\u002F\u002F .NET 6+ — three-way Zip:\nvar grades = new[] { 'A', 'B', 'C' };\nvar triples = names.Zip(scores, grades); \u002F\u002F IEnumerable\u003C(string, int, char)>\n\n\u002F\u002F Stops at the shorter sequence:\nnew[] { 1, 2, 3 }.Zip(new[] { 'a', 'b' }); \u002F\u002F only two pairs: (1,'a'), (2,'b')\n```\n\nCommon use cases: combining a list of keys with a list of values, pairing\nchronological data from two sources, or producing numbered output by zipping with\n`Enumerable.Range`.\n\n**Rule of thumb:** Use `Zip` when two sequences are positionally aligned and you\nwant to process them in lock-step. If the sequences can have different orderings,\na `Join` on a key is safer.\n",{"id":74,"difficulty":25,"q":75,"a":76},"distinct-and-distinctby","How do `Distinct()` and `DistinctBy()` work in LINQ?","`Distinct()` removes duplicate elements using equality comparison on the element\nitself. `DistinctBy()` (.NET 6+) removes duplicates based on a **key selector** —\nkeeping the first element with each distinct key value.\n\n```csharp\nvar nums = new[] { 1, 2, 2, 3, 3, 3 };\nvar unique = nums.Distinct(); \u002F\u002F { 1, 2, 3 }\n\n\u002F\u002F Custom equality for objects — requires IEqualityComparer\u003CT>:\nvar people = new[]\n{\n    new { Name = \"Alice\", Dept = \"Eng\" },\n    new { Name = \"Bob\",   Dept = \"HR\"  },\n    new { Name = \"Alice\", Dept = \"HR\"  }, \u002F\u002F same Name, different Dept\n};\n\n\u002F\u002F Distinct() on anonymous types uses value equality (all fields):\n\u002F\u002F Result: all three — Name+Dept combination is different for each\n\n\u002F\u002F DistinctBy() — deduplicate by a single key, keeping first occurrence:\nvar byName = people.DistinctBy(p => p.Name);\n\u002F\u002F { Alice\u002FEng, Bob\u002FHR } — second Alice dropped\nforeach (var p in byName)\n    Console.WriteLine($\"{p.Name} \u002F {p.Dept}\");\n\n\u002F\u002F Useful for deduplicating DB results by a business key:\nvar latestOrders = orders.DistinctBy(o => o.CustomerId);\n```\n\n`Distinct()` uses the default equality comparer (`EqualityComparer\u003CT>.Default`).\nFor custom comparison pass an `IEqualityComparer\u003CT>` as the second argument.\n`DistinctBy` is the LINQ equivalent of SQL `DISTINCT ON` (PostgreSQL) or a\n`GROUP BY key HAVING ROW_NUMBER() = 1` pattern.\n\n**Rule of thumb:** Use `Distinct()` to deduplicate primitives and value-equal types.\nUse `DistinctBy(x => x.Key)` to pick one representative element per key from a\ncollection of objects.\n",{"id":78,"difficulty":25,"q":79,"a":80},"orderby-vs-thenby","What is the difference between `OrderBy` and `ThenBy` in LINQ?","`OrderBy` \u002F `OrderByDescending` establishes the **primary sort key**. `ThenBy` \u002F\n`ThenByDescending` adds a **secondary (tie-breaking) sort** applied only when the\nprimary key values are equal.\n\n```csharp\nvar employees = new[]\n{\n    new { Name = \"Charlie\", Dept = \"Eng\",  Salary = 80_000 },\n    new { Name = \"Alice\",   Dept = \"HR\",   Salary = 60_000 },\n    new { Name = \"Bob\",     Dept = \"Eng\",  Salary = 90_000 },\n    new { Name = \"Diana\",   Dept = \"HR\",   Salary = 70_000 },\n};\n\n\u002F\u002F Sort by Dept, then by Name within each dept:\nvar sorted = employees\n    .OrderBy(e => e.Dept)\n    .ThenBy(e => e.Name);\n\u002F\u002F Eng\u002FBob, Eng\u002FCharlie, HR\u002FAlice, HR\u002FDiana\n\n\u002F\u002F Multi-level descending:\nvar byDeptThenSalaryDesc = employees\n    .OrderBy(e => e.Dept)\n    .ThenByDescending(e => e.Salary);\n\u002F\u002F Eng\u002FBob(90k), Eng\u002FCharlie(80k), HR\u002FDiana(70k), HR\u002FAlice(60k)\n\n\u002F\u002F Note: chaining OrderBy twice is WRONG — second OrderBy replaces the first:\n\u002F\u002F Bad: employees.OrderBy(e => e.Dept).OrderBy(e => e.Name) — only sorts by Name\n\u002F\u002F Good: .OrderBy(e => e.Dept).ThenBy(e => e.Name)\n```\n\nLINQ's `OrderBy` uses a **stable sort** — elements with equal keys preserve their\noriginal relative order. This makes `ThenBy` reliable and predictable.\n\n**Rule of thumb:** Always use `ThenBy` \u002F `ThenByDescending` for secondary sort\ncriteria, never chain a second `OrderBy`. A chained `OrderBy` silently discards the\nprevious ordering.\n",{"id":82,"difficulty":66,"q":83,"a":84},"linq-performance-pitfalls","What are the most common LINQ performance pitfalls and how do you avoid them?","LINQ's composability can hide significant performance costs. The most common pitfalls\nare multiple enumeration, N+1 queries in EF Core, and misuse of `Count()` vs `Any()`.\n\n```csharp\n\u002F\u002F Pitfall 1 — multiple enumeration: iterates the source twice\nIEnumerable\u003Cint> query = GetExpensiveSequence();\nif (query.Any())          \u002F\u002F first enumeration\n    Process(query.First()); \u002F\u002F second enumeration\n\u002F\u002F Fix: materialise once\nvar list = query.ToList();\nif (list.Count > 0) Process(list[0]);\n\n\u002F\u002F Pitfall 2 — N+1 query: one DB hit per order\nforeach (var order in dbContext.Orders.ToList())       \u002F\u002F 1 query\n    Console.WriteLine(order.Customer.Name);            \u002F\u002F N queries (lazy load)\n\u002F\u002F Fix: eager load with Include\nforeach (var order in dbContext.Orders.Include(o => o.Customer).ToList())\n    Console.WriteLine(order.Customer.Name); \u002F\u002F 1 query with JOIN\n\n\u002F\u002F Pitfall 3 — Count() on IEnumerable iterates the whole sequence\nif (GetItems().Count() > 0) { }   \u002F\u002F O(n)\n\u002F\u002F Fix:\nif (GetItems().Any()) { }         \u002F\u002F O(1) stops at first element\n\n\u002F\u002F Pitfall 4 — Where before Select on large datasets (in memory):\nvar result = items.Select(Transform).Where(x => x.IsValid);\n\u002F\u002F Bad: Transform() called on ALL items\n\u002F\u002F Good: filter first, then project\nvar result2 = items.Where(x => x.IsEligible).Select(Transform);\n```\n\n**Rule of thumb:** Materialise with `ToList()` when you iterate more than once.\nUse `Include()` in EF Core to avoid N+1. Use `Any()` for existence checks. Filter\nwith `Where()` before projecting with `Select()` to minimise work.\n",15,null,{"description":11},"LINQ interview questions — deferred execution, IQueryable vs IEnumerable, Select vs SelectMany, GroupBy, and common performance pitfalls.","dotnet\u002Ffundamentals\u002Flinq","LINQ","Fundamentals","fundamentals","2026-06-22","gJ7OJobzzvZenzfBBIxrrXSSgDwGsGOTF1yIDGLGhhQ",[96,100,103,107,108],{"subtopic":97,"path":98,"order":99},"CLR Runtime","\u002Fdotnet\u002Ffundamentals\u002Fclr-runtime",1,{"subtopic":101,"path":102,"order":12},"Value vs Reference Types","\u002Fdotnet\u002Ffundamentals\u002Fvalue-vs-reference-types",{"subtopic":104,"path":105,"order":106},"Generics","\u002Fdotnet\u002Ffundamentals\u002Fgenerics",3,{"subtopic":90,"path":21,"order":20},{"subtopic":109,"path":110,"order":111},"Nullable Types","\u002Fdotnet\u002Ffundamentals\u002Fnullable-types",5,{"path":113,"title":114},"\u002Fblog\u002Fdotnet-linq-deferred-execution-iqueryable","How LINQ Works in C#: Deferred Execution and IQueryable",1782244117875]