What Is a Predicate Delegate and Where Should It Be Used

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);
}
}

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.

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.

When to use Action Delegate instead of Predicate Delegate

Predicate delegate as the name says constitutes a Predicate which would match a condition/predicate and return bool. Where as Action delegate as the signature says doesn't return anything (one way work).

List<string>.RemoveAll() requires a predicate cause, what if you want to remove all element T from list which matches a specific condition?

When to use Action Delegate instead of Predicate Delegate

Predicate delegate as the name says constitutes a Predicate which would match a condition/predicate and return bool. Where as Action delegate as the signature says doesn't return anything (one way work).

List<string>.RemoveAll() requires a predicate cause, what if you want to remove all element T from list which matches a specific condition?

Delegate Predicates Usefulness

Even when you declare your predicate using a lambda expression, providing an anonymous method instead of a named one, the lambda still only accepts a specific type. It's just that compiler infers the required type (but note that C# actually allows a variation on the lambda syntax where you do explicitly specify the type).

So the two approaches are equally useful; if you understand why one is useful (e.g. the lambda syntax) then you understand why the other is useful.

And they are both useful, because by passing a predicate delegate instance, you allow customization of the behavior of the method you are calling. E.g. in this case, you are using the Array.Find() method. The use of a predicate delegate instance, whether stored first in a local variable or simply passed directly, and whether declared using a named method or an anonymous one, allows the Array.Find() method to implement all the boring, repetitive work of iterating through an array, while allowing callers to provide the interesting, scenario-specific logic.

To be clear, your two examples are really basically identical, especially since you're dealing with a static method for the predicate. There are minor differences in the declarations, but once the optimizing JIT compiler is done with the code, what's executed at runtime is practically the same. Even the IL compiled from your C# program is going to be structurally the same, though there will be some naming differences. You can verify this yourself by comparing the compiled versions, e.g. with the ildasm.exe tool or something like the dotPeek decompiler.

I will also point out that you provided two examples – the use of a local variable and a named method, and the use of an anonymous method without a local variable – but there are at least two other examples that are also similarly identical:

local variable with anonymous method:

  Predicate<Point> predicate = x => x.X * x.Y > 100000;

Point first = Array.Find(points, predicate);

named method without local variable:

  Point first = Array.Find(points, FindPoints);

In that last example, the compiler infers the delegate type, creating the delegate instance automatically, much as it does when you assign the method group name to the local variable.

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);

Delegates: Predicate vs. Action vs. Func

  • Predicate: essentially Func<T, bool>; asks the question "does the specified argument satisfy the condition represented by the delegate?" Used in things like List.FindAll.

  • Action: Perform an action given the arguments. Very general purpose. Not used much in LINQ as it implies side-effects, basically.

  • Func: Used extensively in LINQ, usually to transform the argument, e.g. by projecting a complex structure to one property.

Other important delegates:

  • EventHandler/EventHandler<T>: Used all over WinForms

  • Comparison<T>: Like IComparer<T> but in delegate form.

How do you declare a Predicate Delegate inline?

There's two options, an explicit delegate or a delegate disguised as a lamba construct:

explicit delegate

myObjects.RemoveAll(delegate (MyObject m) { return m.X >= 10; });

lambda

myObjects.RemoveAll(m => m.X >= 10);

Performance wise both are equal. As a matter of fact, both language constructs generate the same IL when compiled. This is because C# 3.0 is basically an extension on C# 2.0, so it compiles to C# 2.0 constructs

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.



Related Topics



Leave a reply



Submit