C#
Predicate Delegate
Programming
Software Development
Delegates

What is a Predicate Delegate and where should it be used?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

A Predicate<T> in C# is a delegate that takes one value of type T and returns bool. In plain terms, it represents a reusable yes-or-no test, which makes it a natural fit for searching, filtering, validation, and rule-based decisions.

What Predicate<T> Represents

The signature of Predicate<T> is simple: one input, one boolean answer. That shape matches questions such as "is this product sellable" or "should this record be removed."

csharp
1using System;
2using System.Collections.Generic;
3
4public class Product
5{
6    public string Name { get; set; } = "";
7    public decimal Price { get; set; }
8    public bool InStock { get; set; }
9}
10
11class Program
12{
13    static void Main()
14    {
15        var items = new List<Product>
16        {
17            new Product { Name = "Keyboard", Price = 49.99m, InStock = true },
18            new Product { Name = "Monitor", Price = 219.00m, InStock = false },
19            new Product { Name = "Mouse", Price = 19.50m, InStock = true }
20        };
21
22        Predicate<Product> canSell = p => p.InStock && p.Price <= 100m;
23        var first = items.Find(canSell);
24
25        Console.WriteLine(first?.Name ?? "none");
26    }
27}

The point is not just syntax. Moving the rule into a named predicate makes the code easier to read, test, and reuse.

Where Predicate<T> Fits Best

The most obvious home for Predicate<T> is APIs that are already designed for it. List<T> exposes several such methods, including Find, FindAll, Exists, and RemoveAll.

csharp
1using System;
2using System.Collections.Generic;
3
4var numbers = new List<int> { 3, 8, 11, 20, 27 };
5Predicate<int> isEven = n => n % 2 == 0;
6
7bool anyEven = numbers.Exists(isEven);
8List<int> evens = numbers.FindAll(isEven);
9numbers.RemoveAll(isEven);
10
11Console.WriteLine(anyEven);
12Console.WriteLine(string.Join(",", evens));
13Console.WriteLine(string.Join(",", numbers));

This reads well because the delegate matches the intent of the API: answer a boolean question about each element.

Predicates also work well in validation layers. A named predicate can express business rules more clearly than repeating the same long lambda in several methods.

csharp
1Predicate<string> validUsername = text =>
2    !string.IsNullOrWhiteSpace(text) &&
3    text.Length >= 4 &&
4    text.Length <= 16;
5
6Console.WriteLine(validUsername("mark"));
7Console.WriteLine(validUsername("x"));

Predicate<T> Versus Func<T, bool>

You can express the same logical rule with Func<T, bool>. In fact, LINQ methods such as Where expect Func<T, bool>, not Predicate<T>. The difference is mostly about API shape and readability, not meaning.

A practical guideline is simple:

  • use Predicate<T> when working with APIs that explicitly ask for it, especially List<T> methods
  • use Func<T, bool> when working with LINQ and more general functional pipelines

The logic is the same. The delegate type just follows the method signature that the framework exposes.

Keep Predicates Focused and Side-Effect Free

A predicate should answer a question, not perform work with side effects. If the lambda starts updating counters, writing logs, or mutating external state, the code becomes harder to reason about.

As rules become more complex, compose small predicates instead of writing one huge inline condition.

csharp
1static Predicate<Product> PriceAtMost(decimal limit) => p => p.Price <= limit;
2static Predicate<Product> IsAvailable() => p => p.InStock;
3
4Predicate<Product> affordableAndAvailable =
5    p => PriceAtMost(100m)(p) && IsAvailable()(p);

This style keeps each rule single-purpose and makes tests easier to write.

Common Pitfalls

Writing very long inline predicates makes calling code hard to read. Extract a named predicate when the rule grows beyond a simple condition.

Mixing side effects into a predicate breaks the mental model of a pure yes-or-no test.

Using Predicate<T> where an API expects Func<T, bool> can cause confusion. Match the delegate type to the API you are calling.

Summary

  • 'Predicate<T> is a delegate for reusable boolean tests.'
  • It is especially useful with List<T> methods such as Find, FindAll, Exists, and RemoveAll.
  • It improves readability by naming search and validation rules.
  • Keep predicates focused, reusable, and free of side effects.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.