LINQ: Where Query - A Beginner's Guide
C Sharp .NET LINQ

LINQ: Where Query - A Beginner's Guide

Mishel Shaji
Mishel Shaji

The Where() method is one of the most important and frequently used methods in LINQ. If you are learning LINQ for the first time, understanding the Where() method properly is extremely important because it is used in almost every real-world .NET application.

If you understand how an if statement works inside a loop, you already understand the logic of Where. The difference is that Where makes your code much cleaner and more "declarative"—meaning you tell the computer what you want instead of how to loop through it.

💡
The Where() method is used to filter data from a collection based on a condition.

How it Works: The Predicate

The Where method takes something called a Predicate. A predicate is simply a function that takes an item from the collection and returns either true or false.

It checks every item in the collection one by one. If the item satisfies the condition based on the predicate, it is included in the result. If the condition is false, the item is ignored.

  • If the result is true, the item stays in the results.
  • If the result is false, the item is filtered out.

Basic Example: Filtering Strings

Imagine you have a list of fruits, and you only want to find the ones that have more than 5 letters.

The Old Way (Imperative)

List<string> fruits = new List<string> { "Apple", "Banana", "Cherry", "Kiwi", "Strawberry" };
List<string> longFruits = new List<string>();

foreach (var fruit in fruits)
{
    if (fruit.Length > 5)
    {
        longFruits.Add(fruit);
    }
}

The LINQ Way

using System.Linq;

List<string> fruits = new List<string> { "Apple", "Banana", "Cherry", "Kiwi", "Strawberry" };

var longFruits = fruits.Where(f => f.Length > 5).ToList();

// Result: "Banana", "Cherry", "Strawberry"

Example: Using Where() with Strings

The Where() method can also filter string collections.

Example – Names Starting with J

List<string> names = new()
{
    "John",
    "David",
    "James",
    "Sam"
};

var result = names.Where(name => name.StartsWith("J"));

foreach (var item in result)
{
    Console.WriteLine(item);
}

Output

John
James

Explanation

The StartsWith() method checks whether the string begins with a specific letter.

name.StartsWith("J")

returns true for:

  • John
  • James

So only those names appear in the result.

Pro Tip: The Index in Where

Did you know that Where can also give you the position (index) of the item it is currently checking? This is a hidden gem in LINQ.

int[] numbers = { 10, 20, 30, 40, 50 };

// Filter numbers that are greater than 25 AND are at an even index (0, 2, 4...)
var result = numbers.Where((num, index) => num > 25 && index % 2 == 0);

// Result: 30 (index 2) and 50 (index 4)

Example: Using Where() with Objects

In real applications, developers mostly work with objects instead of simple numbers.

This is where LINQ becomes extremely powerful.

class Student
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public int Marks { get; set; }
}

List<Student> students = new()
{
    new Student() { Id = 1, Name = "John", Marks = 90 },
    new Student() { Id = 2, Name = "David", Marks = 65 },
    new Student() { Id = 3, Name = "Sam", Marks = 85 },
    new Student() { Id = 4, Name = "Mary", Marks = 40 }
};

var toppers = students.Where(student => student.Marks >= 80);

foreach (var student in toppers)
{
    Console.WriteLine(student.Name);
}

Output

John
Sam

Example Using AND Operator

var result = students.Where(x => x.Marks > 70 && x.Name.StartsWith("J"));

This means:

  • Marks must be greater than 70
  • AND name must start with J

Both conditions must be true.

Example Using OR Operator

var result = students.Where(x => x.Marks > 80 || x.Name == "David");

This means:

  • Marks greater than 80
  • OR student name is David

Either condition can be true.

Common Pitfalls to Avoid

  1. Null Collections: Always ensure your list is not null before calling .Where(), otherwise your app will crash with a NullReferenceException.
  2. Case Sensitivity: When filtering strings (like e.Department == "IT"), remember that "it" is not the same as "IT". Use .Equals("IT", StringComparison.OrdinalIgnoreCase) for safer filtering.
  3. Deferred Execution: Remember from our previous lesson that Where doesn't actually filter the data until you look at it (like in a foreach or .ToList()).

Practice Questions

1. Write a LINQ Where query to find all numbers in a list that are between 10 and 20 (inclusive).

  • Answer: numbers.Where(n => n >= 10 && n <= 20);

2. If you have a list of User objects, how would you find all users whose Email property is null or empty?

  • Answer: users.Where(u => string.IsNullOrEmpty(u.Email));

3. What happens to the original list when you run a Where query on it?

  • Answer: Nothing. LINQ never changes the original data; it creates a new sequence of results.

4. Can you use a custom function inside a Where clause, or must it always be a short lambda?

  • Answer: You can use a custom function! For example: Where(e => MyCustomCheck(e)). This is very helpful for complex logic that is too long for a single line.