What Is a Predicate in C#

What is a predicate in c#?

Predicate<T> is a functional construct providing a convenient way of basically testing if something is true of a given T object.

For example suppose I have a class:

class Person {
public string Name { get; set; }
public int Age { get; set; }
}

Now let's say I have a List<Person> people and I want to know if there's anyone named Oscar in the list.

Without using a Predicate<Person> (or Linq, or any of that fancy stuff), I could always accomplish this by doing the following:

Person oscar = null;
foreach (Person person in people) {
if (person.Name == "Oscar") {
oscar = person;
break;
}
}

if (oscar != null) {
// Oscar exists!
}

This is fine, but then let's say I want to check if there's a person named "Ruth"? Or a person whose age is 17?

Using a Predicate<Person>, I can find these things using a LOT less code:

Predicate<Person> oscarFinder = (Person p) => { return p.Name == "Oscar"; };
Predicate<Person> ruthFinder = (Person p) => { return p.Name == "Ruth"; };
Predicate<Person> seventeenYearOldFinder = (Person p) => { return p.Age == 17; };

Person oscar = people.Find(oscarFinder);
Person ruth = people.Find(ruthFinder);
Person seventeenYearOld = people.Find(seventeenYearOldFinder);

Notice I said a lot less code, not a lot faster. A common misconception developers have is that if something takes one line, it must perform better than something that takes ten lines. But behind the scenes, the Find method, which takes a Predicate<T>, is just enumerating after all. The same is true for a lot of Linq's functionality.

So let's take a look at the specific code in your question:

Predicate<int> pre = delegate(int a){ return a % 2 == 0; };

Here we have a Predicate<int> pre that takes an int a and returns a % 2 == 0. This is essentially testing for an even number. What that means is:

pre(1) == false;
pre(2) == true;

And so on. This also means, if you have a List<int> ints and you want to find the first even number, you can just do this:

int firstEven = ints.Find(pre);

Of course, as with any other type that you can use in code, it's a good idea to give your variables descriptive names; so I would advise changing the above pre to something like evenFinder or isEven -- something along those lines. Then the above code is a lot clearer:

int firstEven = ints.Find(evenFinder);

When do I use a predicate

Firstly, I'll summarize delegates and lambda expressions.

Delegates


In C#, delegates allow you to create types which represent functions. In other words, delegates allow you to save a reference to a method in a variable. Once, we store a reference to that method, we can use this variable to call the method it is referring to. So you are indirectly calling the method. The term "delegate" in C# very well lives up to the literal meaning of delegate.

To store a reference to a method, you first need to create a compatible delegate:

delegate int MyDelegate(string parameter)

The above statement creates a delegate that can hold a reference to any method that has a return type of int and takes a single string as parameter. For instance, I'm creating a trivial class and a method here for demo:

class AClass 
{
public int StringLength(string str) { return str.Length; }
}

Once you create a delegate, you can use it like a type:

AClass obj = new AClass()
MyDelegate d = obj.StringLength

Notice I have skipped the parentheses after StringLength. Now I can do this:

int length = d("Hello");

This will indirectly call, obj.StringLength() and the value it returns will be returned by d and stored in length.

There's more to delegates like multicast delegates which are beyond the scope of this answer.

Why are delegates powerful?

They help you to easily pass around functions/methods just like objects. You can pass your own method to a class that knows nothing about your method but will call it later through the delegate. This allows you to embed your custom logic into code that you know nothing about.

Lambda Expressions


A lambda expression is nothing but a function literal. It helps to quickly create a function without creating a new class and a new method. In the previous example, I have created a class called AClass with a method StringLength. You can see that all the method body consists is of a single line. With lambdas, you can skip creating a class and a method and directly specify the method body:

MyDelegate d = str => str.Length;

The Predicate<T> Delegate


Predicate<T> is just another delegate as well, defined as follows:

delegate bool Predicate<T>(T obj)

This is a delegate with a generic parameter. This allows you to pass it a parameter of any type which will be specified later when the delegate variable is created but the return type is always bool. A predicate is, in essence, just a condition, that can be either true or false.

Coming to your question, with predicates, you can pass in such a condition to a method so that the method can use it to check if it holds true for something that is private to that class. You are basically passing in logic that will be executed later.

A common use case of predicates is filtering. If I have a collection of elements, and I want to filter the elements and obtain only those elements for which a condition holds true, I can use a Predicate<T> parameter:


public List<int> Filter(List<int> list, Predicate<int> filter)
{
public var filteredList = new List<int>();
foreach (int element in list)
{
if (filter(element))
{
filteredList.Add(element); //Add to list only if condition holds true for the element
}

}
}

Now, suppose, I have a list and I want only the even numbers and numbers greater than 5, then I can simply do this:

var numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
var evenNumbers = Filter(numbers, element => element % 2 == 0); // 2, 4, 6, 8
var numbersGreaterThan5 = Filter(numbers, element => element > 5); // 6, 7, 8, 9

In practice, you will hardly have to create a custom Filter() method since System.Linq already has a method/LINQ operator called Where() that does this for you. The parameter to this Where() method is not a Predicate<T> but an identical(compatibility-wise) Func<T, bool> which is another delegate defined as follows:

delegate TResult Func<in T, out TResult>(T arg)

Func<T, bool> and Predicate<T> are therefore identical regards to the methods they can reference. Moreover, you can create your own delegate with the same signature as the predicate. The framework has a bunch of them defined to make life a bit easier for you.

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

A predicate is a function that returns true or false. A predicate delegate is a reference to a predicate.

So basically a predicate delegate is a reference to a function that returns true or false. Predicates are very useful for filtering a list of values - here is an example.

using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<int> list = new List<int> { 1, 2, 3 };

Predicate<int> predicate = new Predicate<int>(greaterThanTwo);

List<int> newList = list.FindAll(predicate);
}

static bool greaterThanTwo(int arg)
{
return arg > 2;
}
}

Now if you are using C# 3 you can use a lambda to represent the predicate in a cleaner fashion:

using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<int> list = new List<int> { 1, 2, 3 };

List<int> newList = list.FindAll(i => i > 2);
}
}

differences between Predicate and Func delegate in C#

Predicate<T> was introduced in .NET 2.0 with the introduction of generics. It's a delegate taking one parameter and returning a bool.

However, with the introduction of LINQ in .NET 3.5, a need was identified for two families of generic types - Func and Action (the difference being on whether they return anything) taking up to 16 41 generic input parameters and being generic in their return types. If Func had existed first, Predicate<T> would never have been created in the first place. It's an unnecessarily specialized delegate type.

For backwards compatibility reasons though, they cannot now remove Predicate<T> from the framework. Some may argue that its name does convey specific semantic meaning but I'd struggle to identify many situations where any Func<T,bool> (or Func<T1,T2,bool>, etc.) wouldn't be considered a predicate.


14 in .NET 3.5, 16 in .NET 4 and later.

What is the difference between a lambda expression and a predicate in .NET?

A predicate is delegate (function object) that returns a boolean value. Lambda expressions can be used to define any anonymous function, which includes predicates, e.g. to express a predicate in the form of a lambda expression:

Predicate<int> isEven2 = x => x % 2 == 0;

which is functionally equivalent to:

Func<int,bool> isEven = x => x % 2 == 0;

Action, Func and Predicate delegates - C#

Predicate<T> is a delegate that takes a T and returns a bool.

It's completely equivalent to Func<T, bool>.

The difference is that Predicate<T> was added in .Net 2.0, whereas all of the Func<*> delegates were added in .Net 3.5. (except the ones with >8 parameters, which were added in .Net 4.0)

The LINQ-like methods in List<T> (FindAll(), TrueForAll(), etc) take Predicate<T>s.

To answer your second question, void cannot be used as a generic parameter.

How to pass a predicate as parameter c#

private List<thing> GetItems(Func<thing, bool> filter = null)
{
return rawList.Where(filter ?? (s => true)).ToList();
}

In this expression s => true is the fallback filter which is evaluated if the argument filter is null. It just takes each entry of the list (as s) and returns true.

Passing a predicate as a parameter c#

public Egg(Func<IBird> createBird) is not a function, it's the constructor of the Egg class. Since the Egg class must Hatch birds, it needs to create birds. Func<IBird> is a delegate, i.e., a value representing a reference to a method. In this specific case it is representing a factory method. A predicate would be a method or delegate returning a Boolean. Through this parameter you can pass any method creating IBirds. Since the IBird interface does not specify an explicit implementation of a bird, you could initialize Egg with different methods creating different bird types. Some requiring constructor parameters, some not.

You would implement Egg like this

public class Egg
{
private readonly Func<IBird> _createBird;

public Egg(Func<IBird> createBird)
{
_createBird = createBird; // No "()". createBird is not called, just assigned.
}

public IBird Hatch()
{
return _createBird(); // Here createBird is called, therefore the "()".
}
}

Now, the Hatch method can create birds, without having the knowledge about how or which type of bird to create, through the intermediate of the _createBird delegate.

How would you create an egg? Well, first you need some bird implementation e.g.:

public class BlackBird : IBird
{
... your implementation goes here
}

Then you need a method creating and returning a IBird. E.g.:

IBird CreateBlackBird()
{
return new BlackBird();
}

You can then create an egg with

var egg = new Egg(CreateBlackBird); // No "()". CreateBlackBird is not called but referenced.
IBird newBird = egg.Hatch();

Make sure to pass the method without parameter list, i.e. without parentheses, because you don't want to call the CreateBlackBird method at this point, you want to pass it over to the constructor, where it is stored in the private field _createBird to be used later.

A lambda expression creates an anonymous delegate on the fly:

var egg = new Egg(() => new BlackBird());

() => new BlackBird() is a lambda expression. It is equivalent to the CreateBlackBird method. The return type is not specified and is inferred from the parameter type of the Egg constructor. It has no name. Only the parameter braces are remaining from the method header. => replaces the return keyword.

After having implemented an additional bird class with a color as constructor parameter, you can write

var egg = new Egg(() => new ColoredBird(Color.Blue));

See also:

  • Lambda expressions (C# Programming Guide)
  • Beginner's Guide to Delegates, Funcs and Actions in C#
  • What is constructor injection?

How to define a predicate as a function argument

Here's a trivial example of using a predicate in a function.

static void CheckRandomValueAgainstCriteria(Predicate<int> predicate, int maxValue)
{
Random random = new Random();
int value = random.Next(0, maxValue);

Console.WriteLine(value);

if (predicate(value))
{
Console.WriteLine("The random value met your criteria.");
}
else
{
Console.WriteLine("The random value did not meet your criteria.");
}
}

...

CheckRandomValueAgainstCriteria(i => i < 20, 40);


Related Topics



Leave a reply



Submit