C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
159: Common C# Interview Questions on LINQ
If you've spent any time interviewing for C# roles, you know that LINQ is practically a mandatory topic. Interviewers love it because it's the quickest way to see if you understand the difference between "writing code that works" and "writing code that is efficient." They aren't just checking if you know the syntax; they're checking if you understand deferred execution and memory allocation.
Instead of just listing questions, let's build a quick Order processing snippet. This will cover the three most common "gotchas" I see people trip over in technical rounds.
Setting up our Order Data
I'll start with two simple classes: an Order and a LineItem. This one-to-many relationship is the perfect playground for testing your knowledge of flattening collections.
public class LineItem
{
public string ProductName { get; set; }
public decimal Price { get; set; }
}
public class Order
{
public int OrderId { get; set; }
public List<LineItem> Items { get; set; } = new();
public decimal TotalAmount => Items.Sum(x => x.Price);
}
Now, let's imagine the interviewer asks you to get a distinct list of all product names sold in orders that totaled over $100.
Flattening the Product Lists
Here is where a lot of candidates stumble. My first instinct—and the mistake I've made more than once early in my career—is to use Select. Let's see what happens when I do that.
var orders = new List<Order> { /* ... data ... */ };
// Mistake: This returns an IEnumerable of lists
var productNames = orders
.Where(o => o.TotalAmount > 100)
.Select(o => o.Items.Select(i => i.ProductName))
.Distinct();
Wait. If I hover over productNames, I'll see the type is IEnumerable<IEnumerable<string>>. I didn't get a list of products; I got a list of "lists of products." This is a classic interview trap. To fix this, I need SelectMany. It "flattens" the nested collections into a single sequence.
// The correct way
var productNames = orders
.Where(o => o.TotalAmount > 100)
.SelectMany(o => o.Items.Select(i => i.ProductName))
.Distinct()
.ToList();
Testing Deferred Execution
Now, let's talk about the "When does this actually run?" question. This is the core of the IEnumerable vs IQueryable debate. I'm going to write a query, but I won't call ToList() immediately.
var expensiveOrdersQuery = orders.Where(o => o.TotalAmount > 500);
// I'm adding a new expensive order AFTER the query was defined
orders.Add(new Order {
OrderId = 99,
Items = new List<LineItem> { new LineItem { ProductName = "Laptop", Price = 1200 } }
});
foreach (var order in expensiveOrdersQuery)
{
Console.WriteLine($"Order {order.OrderId} is expensive!");
}
If you think the new "Laptop" order won't show up, you're thinking of a List, not a LINQ query. Because expensiveOrdersQuery is just a set of instructions (deferred execution), it doesn't actually filter the data until the foreach loop starts. This is a huge performance win when working with databases, but a common source of bugs if you aren't expecting it.
The 'Any' vs 'Count' Trap
Finally, a quick tip on performance that often comes up during code reviews or senior-level interviews. Suppose you want to check if there are any orders that exceed $1,000.
You might be tempted to write if (orders.Where(o => o.TotalAmount > 1000).Count() > 0). Don't do that. Count() has to iterate through the entire collection to find the total number of matches. Any() stops the moment it finds the very first match. It's the difference between scanning an entire warehouse to see if a product exists versus just finding one and stopping.
// Do this
if (orders.Any(o => o.TotalAmount > 1000))
{
Console.WriteLine("We have some high-ticket orders!");
}
📋 Practical Task
Exercise: Refactoring the Project-Employee Auditor
You are reviewing a junior developer's code for a project auditing tool. The current code is inefficient and contains a common LINQ mistake regarding nested collections. Your goal is to refactor the GetAllUniqueEmployeeNames method to be more performant and return the correct type.
Current Buggy Code:
public class Project
{
public string ProjectName { get; set; }
public List<Employee> Team { get; set; } = new();
}
public class Employee
{
public string Name { get; set; }
public bool IsContractor { get; set; }
}
public class Auditor
{
public List<IEnumerable<string>> GetAllUniqueEmployeeNames(List<Project> projects)
{
// This is currently returning a list of lists and using Count() inefficiently
var result = projects
.Where(p => p.Team.Count() > 0)
.Select(p => p.Team.Select(e => e.Name))
.Distinct()
.ToList();
return result;
}
}
Requirements for your fix:
- Change the return type from
List<IEnumerable<string>>toList<string>. - Use
SelectManyto flatten the employees into a single list of names. - Replace the
Count() > 0check with a more efficient LINQ method. - Ensure the final list contains only unique names.
There are no comments for now.