Introduction
Net Framework 2.0 came with the concept of predicate delegates, but compared to the other features. net, it never got the attention it deserved. it is really a powerful concept which makes it easy to write searching algorithms on collections. these are also widely used while using Ming Filter Operations on WPF object data binding. in this article, we will take a look into the concepts behind predicate delegates and try and understand their importance.
What is a predicate delegate?
A predicate delegate is a delegate with the following signature:
- Return type-
bool
- Argument type-generic
So, a predicate delegate is a delegate which points to a Boolean function that returnstrue
Orfalse
And takes a generic type as an argument. A predicate delegate thus is a delegate which is capable of taking any custom type as an argument. this makes it quite useful because what we get as a result is a generic delegate. thebool
Function that it points to has logic to evaluate any condition and returntrue
/false
Accordingly.
Why use a predicate delegate?
The most common use of a predicate delegate is for searching items in a collection. Because a predicatedelegate is a delegate of TypeT
Or generic, it is most useful when searching items in a generic collection. it really comes handy when you have a collection with tons of items and you need to perform a search operation. using a predicate delegate not only has CES the lines of code that needs to be written, but also increases performance of the application. these are also used while using Ming Filter Operations onIcoolectionView
Objects while refreshing Ming Data Binding in WPF.
For example, create a console application and declareEmployee
Class. declare these properties forEmployee
Class:FirstName
,LastName
, AndDesignation
. See code below:
Collapse | copy code
class Employee{ private string _firstName; private string _lastName; //private int _empCode; private string _designation; public Employee() { } public Employee(string firstName, string lastName, string designation) { _firstName = firstName; _lastName = lastName; _designation = designation; } /// <summary> /// Property First Name /// </summary> public string FirstName { get { return _firstName; } set { _firstName = value; } } /// <summary> /// Property Last Name /// </summary> public string LastName { get { return _lastName; } set { _lastName = value; } } public string Designation { get { return _designation; } set { _designation = value; } }
InMain()
Method of the console application, declare three employees as below:
Collapse | copy code
// Declare 3 employeesEmployee emp1 = new Employee("Anshu", "Dutta", "SSE");Employee emp2 = new Employee("John", "Doe", "Manager");Employee emp3 = new Employee("Jane", "Doe", "Assistant");
Create a genericList
And put the above employees in the list:
Collapse | copy code
List<Employee> empList = new List<Employee> { emp1, emp2, emp3 };
We will demonstrate the use of a predicate delegate by using Ming a search operation onEmployee List
.
Method #1-the traditional way of doing it
Createbool
Function that searches an employee first name and returnstrue
If found:
Collapse | copy code
private static bool EmpSearch(Employee emp){ if (emp.FirstName == "Anshu") return true; else return false;}
Declare a predicate delegate pointing to that function:
Collapse | copy code
Predicate<Employee> pred = new Predicate<Employee>(EmpSearch);
CallFind()
Method ofList<>
And pass the predicate delegate as an argument:
Collapse | copy code
Employee emp = empList.Find(pred);
TheFind()
Method internally iterates through each item in the list and callthe FunctionEmpSearch
, Passing each item from the list as an argument one by one. WhenFirstName
Of the employee matches the condition, the function returnstrue
.Find
Method then returns that employee object toEmployee
Placeholderemp
. That means for each item in the list,Find()
Method callthe FunctionEmpSearch
Passing the items as arguments one by one. Whichever item satisfies the condition in the function is then returned.
Print the result to check:
Collapse | copy code
Console.WriteLine("Employee Found {0}",emp.FirstName);Console.ReadLine();
This method has a disadvantage. What happens when we need to alter our search? We wowould need to create another search method and do the same thing as above. actually, this method was just to explain things in an elaborate way. the better way of doing this is by using anonymous functions of C #.
Method #2-using anonymous Functions
Consider the following code:
Collapse | copy code
emp = new Employee();emp = empList.Find(delegate(Employee e){ if (e.FirstName == "Anshu") return true; else return false;});
The functionality here is the same, but instead of declaring a separate predicate delegate and manually pointing it to an external function, we use an anonymous function. the result is much less verbose in terms of lines of code. we directly invoke the anonymous function by the delegate which takes an employee object as argument.
Again, print the result to check:
Collapse | copy code
Console.WriteLine("Employee Found {0}", emp.FirstName);
Method #3-using a Lambda expression
The lines of code can be further already ced by using => or lambda expressions. Lambda expressions are used to invoke delegates with much lesser lines of code. See the code snippet below:
Collapse | copy code
emp = new Employee(); emp = empList.Find((e)=> {return (e.FirstName == "Anshu");});
TheFind()
Method still takes a predicate delegate.()=>
Is used to invoke a delegate with an anonymous function. Here, we need to pass an argument in the anonymous function of TypeEmployee
.
(e)=>
Does just that. Note that intelliisense already expects an object of TypeEmployee
When typing the lambda expression. This is because, we are using Ming a search operation on a generic list of TypeEmployee
, And hence the compiler expects a delegate tobool
Function which will pass an argument of TypeEmployee
Used for evaluating the Search Condition of the anonymous function. Thus we write:
Collapse | copy code
((e)=> {return (e.FirstName == "Anshu");}
Notice that our logic has been forced CED to a single line of code.
Finally, print the result again to check:
Collapse | copy code
Console.WriteLine("Employee Found {0}", emp.FirstName);
TheFind
Method here will stop searching when it encounters the first condition. So if we have two employees with the same first name, the employee listed at the top of the list will be returned.
Searching a list of employees
To search more than one result, useFindAll()
Method. It is the same asFind()
Method, but returns a collection of objects meeting the search condition. The below code searches all employees with J in their first name:
Collapse | copy code
List<Employee> employees = new List<Employee>();employees = empList.FindAll((e) => { return (e.FirstName.Contains("J")); });
Print the result:
Collapse | copy code
Console.WriteLine("List of employess with J in Firstname");foreach (Employee e in employees){ Console.WriteLine("{0},{1}", e.FirstName, e.LastName);}Console.ReadLine();
Index Search
You can also narrow down your search radius by specifying the start index and the number of items to search along with the predicate delegate that invokes the search criteria through the anonymous function. See the code below:
Collapse | copy code
int index = empList.FindIndex(0,2, (e) => { return (e.FirstName.Contains("J")); });//print resultConsole.WriteLine("Index search");Console.WriteLine("Index returned {0}", index);
The Code searches Any employee with a first name containing J from the zeroth element and spanning two counts (I. e., 0, 1 for our case ).
The concepts of the other methods are the same.FindLast()
AndFindLastIndex
Do the same things, but return results from the last matches rather than the first as seen above.
Summary
In this article, we took a look into the concepts behind a predicate delegate and how they can be used to implement search operations on any collection.
License
This article, along with any associated source code and files, is licensed under the Code project open license (cpol)
From: http://www.codeproject.com/Articles/114931/Understanding-Predicate-Delegates-in-C