Overview
LINQ revolutionized C# development by bringing functional programming concepts to .NET. Understanding LINQ deeply is essential for writing clean, efficient code and is a frequent interview topic for mid-level and above positions.
Core Concepts
Query Syntax vs Method Syntax
var products = GetProducts();
// Query syntax - more readable for complex queries
var queryResult = from p in products
where p.Price > 50
orderby p.Name
select new { p.Name, p.Price };
// Method syntax - more flexible and composable
var methodResult = products
.Where(p => p.Price > 50)
.OrderBy(p => p.Name)
.Select(p => new { p.Name, p.Price });
Deferred vs Immediate Execution
var numbers = new List<int> { 1, 2, 3 };
// Deferred execution - query stored, not executed
var query = numbers.Where(n => n > 1);
numbers.Add(4); // Affects query results!
foreach (var n in query) // Executes here
Console.WriteLine(n); // Output: 2, 3, 4
// Immediate execution with .ToList(), .ToArray(), .Count()
var list = numbers.Where(n => n > 1).ToList(); // Executes immediately
numbers.Add(5); // Doesn't affect list
Common LINQ Operations
var products = GetProducts();
// Filtering
var expensive = products.Where(p => p.Price > 100);
// Projection
var names = products.Select(p => p.Name);
var summary = products.Select(p => new { p.Name, Tax = p.Price * 0.1m });
// Ordering
var sorted = products.OrderBy(p => p.Price).ThenBy(p => p.Name);
// Grouping
var byCategory = products.GroupBy(p => p.Category);
foreach (var group in byCategory)
{
Console.WriteLine($"Category: {group.Key}");
foreach (var product in group)
Console.WriteLine($" {product.Name}");
}
// Aggregation
var total = products.Sum(p => p.Price);
var average = products.Average(p => p.Price);
var maxPrice = products.Max(p => p.Price);
Joining Data
var customers = GetCustomers();
var orders = GetOrders();
// Inner join
var customerOrders = from c in customers
join o in orders on c.Id equals o.CustomerId
select new { c.Name, o.OrderDate, o.Total };
// Left join (group join)
var customersWithOrders = from c in customers
join o in orders on c.Id equals o.CustomerId into orderGroup
select new { Customer = c, Orders = orderGroup };
Bad vs Good Examples
Bad: Multiple Enumerations
// Bad - enumerates collection 3 times
var items = GetExpensiveItems();
var count = items.Count();
var sum = items.Sum(x => x.Price);
var avg = items.Average(x => x.Price);
Good: Single Enumeration
// Good - enumerates once
var items = GetExpensiveItems().ToList(); // Materialize once
var count = items.Count;
var sum = items.Sum(x => x.Price);
var avg = items.Average(x => x.Price);
Bad: Inefficient Filtering
// Bad - filters, then filters again
var result = products
.Where(p => p.IsActive)
.Select(p => p.Name)
.Where(name => name.StartsWith("A"));
Good: Combined Filtering
// Good - filter once
var result = products
.Where(p => p.IsActive && p.Name.StartsWith("A"))
.Select(p => p.Name);
Interview Tips
Tip 1: Always mention deferred execution when discussing LINQ. It's a common "gotcha" question.
Tip 2: Know when to use
.ToList()or.ToArray()to materialize results, especially before multiple enumerations.
Tip 3: Understand that LINQ to Entities (EF Core) translates to SQL - some operations force client-side evaluation.
Common Interview Questions
-
What's the difference between IEnumerable and IQueryable?
IEnumerable<T>: In-memory queries, client-side execution.IQueryable<T>: Expression tree-based, allows provider (like EF) to translate to SQL.
-
Explain deferred execution in LINQ.
- Query doesn't execute when defined, only when enumerated (foreach, ToList, Count, etc.). Allows query composition but can cause unexpected behavior if source changes.
-
What's the difference between Select and SelectMany?
Select: One-to-one projection.SelectMany: Flattens nested collections (one-to-many), like SQLJOIN.
-
When should you use ToList() or ToArray()?
- When you need to enumerate multiple times, when you want a snapshot of current data, or when you need indexed access.
-
How does LINQ improve code readability?
- Declarative syntax (what, not how), chainable operations, less boilerplate than loops, compile-time checking.
-
What are the performance implications of LINQ?
- Slight overhead vs hand-written loops, but negligible in most cases. Real issues: multiple enumerations, inefficient queries, client-side evaluation in EF.
-
Can you modify a collection while enumerating it with LINQ?
- No, throws
InvalidOperationException. Must materialize first (.ToList()) or use different approach.
- No, throws