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
33: LINQ Fundamentals
I've spent way too many hours of my career writing the same pattern: create an empty list, loop through a collection, check an if statement, and add the matching item to that new list. It's tedious, it's boilerplate, and frankly, it clutters the logic of what we're actually trying to achieve. Let's look at a real scenario and see if we can find a cleaner way to handle data.
Imagine we're building a simple inventory manager for a game shop. I've got a list of products, and I only want to find the ones that are currently in stock and cost less than $50.
var products = new List<Product>
{
new Product { Name = "Retro Console", Price = 89.99m, InStock = true },
new Product { Name = "Controller", Price = 25.00m, InStock = true },
new Product { Name = "Game Card A", Price = 15.00m, InStock = false },
new Product { Name = "Game Card B", Price = 12.00m, InStock = true },
new Product { Name = "Headset", Price = 45.00m, InStock = true }
};
// The "old school" way
var affordableInStock = new List<Product>();
foreach (var p in products)
{
if (p.InStock && p.Price < 50)
{
affordableInStock.Add(p);
}
}
Replacing the loop with a filter
That works, but it's noisy. I'm telling the computer how to do it (create list, loop, check, add) rather than what I want. This is where Language Integrated Query (LINQ) comes in. I'll try using the Where method. I've noticed it takes a lambda expression—essentially a mini-function—to define the criteria.
using System.Linq;
// ...
var filtered = products.Where(p => p.InStock && p.Price < 50);
At first glance, this is beautiful. One line. But if I try to debug this and hover over filtered, I'll see it isn't actually a List<Product>. It's an IEnumerable<Product>. This is a crucial distinction. LINQ uses "deferred execution." The filtering hasn't actually happened yet; C# has just stored the instructions on how to filter the list when we finally decide to iterate over it.
If I need this to be a concrete list right now—maybe because I'm passing it to a method that requires a List—I have to force the execution. I'll add .ToList() to the end.
var filteredList = products.Where(p => p.InStock && p.Price < 50).ToList();
Narrowing the focus with projection
Now, let's say I don't actually need the whole Product object. I just want a list of the names of these affordable items to display in a UI dropdown. Right now, I'd have to loop through my filteredList again to extract the names. That feels inefficient.
I'll try the Select method. In LINQ terms, this is called "projection." It transforms each element into something else.
var names = products.Where(p => p.InStock && p.Price < 50)
.Select(p => p.Name)
.ToList();
I love this because I can chain these operations. The data flows through a pipeline:
First, we filter out the expensive or out-of-stock items (Where), then we strip away everything but the name (Select), and finally, we solidify the result into a list (ToList).
Wait, what about Query Syntax?
If you look at older C# code or certain tutorials, you'll see a completely different style that looks almost like SQL. It's called Query Syntax. I'll try rewriting the same logic using this style to see if it's actually better.
var namesQuery = from p in products
where p.InStock && p.Price < 50
select p.Name;
Honestly? It's a matter of taste. Some people find this more readable for complex queries with multiple joins. However, in my experience, the method syntax (the .Where().Select() chain) is far more common in professional codebases and is generally more flexible when you start getting into more advanced LINQ operators. I'll stick with the method syntax for now, but it's good to recognize the query style so you aren't confused when you see it in a legacy project.
📋 Practical Task
Filtering and Projecting the Employee Directory
You are tasked with creating a report from a list of employees. You have a Employee class with the following properties: Name (string), Department (string), and YearsOfService (int).
Given the following list:
var employees = new List<Employee>
{
new Employee { Name = "Alice", Department = "Engineering", YearsOfService = 5 },
new Employee { Name = "Bob", Department = "Sales", YearsOfService = 2 },
new Employee { Name = "Charlie", Department = "Engineering", YearsOfService = 10 },
new Employee { Name = "Diana", Department = "HR", YearsOfService = 8 },
new Employee { Name = "Eve", Department = "Engineering", YearsOfService = 3 }
};
Write a LINQ query using method syntax that does the following:
- Filters the list to include only employees in the "Engineering" department.
- Further filters those employees to include only those with more than 4 years of service.
- Projects the result so you only have a list of their
Namevalues. - Converts the final result into a
List<string>.
There are no comments for now.