Predicates

Predicates are one-trick pony delegates, used only for methods that have a specific signature: returning a boolean value, and taking exactly one argument — the argument type can be anything, though.

public delegate bool Predicate<T>(T alpha);

These can be useful as arguments to methods, allowing you to dynamically define the objective. For example, "Array.Find" expects an array as the first argument (what you're searching through) and a Predicate as the second argument (what you're searching for). Thus, I could build whatever Predicate method I like to search for specific Student objects enrolled into my Course. Let's say, a student who's done poorly on the first exam, but also really well on the Final.

public class Course
{
Student[] enrolled;
unshort size, capacity;

public void wellDone()
{
Predicate<Student> mySearch = thereGoesMyHero;
Student myHero = Array.Find(enrolled, mySearch);

if (myHero != null)
{
myHero.print();
System.Console.WriteLine("Watch 'em as they go!");
}
}

private static bool thereGoesMyHero(Student alpha)
{
return alpha.firstExam < 65 && alpha.finalExam > 85;
}
}


The use of predicates can also be utilized through what are called "lambda expressions" or "anonymous functions". These are chunks of code with no formal name to be used or to refer to them by, giving way to the creation of sort of one-time use functions. You denote these lambda expressions using => notation. For example, I'll convert the above example into one using a lambda expression instead.

public class Course
{
Student[] enrolled;
unshort size, capacity;

public void wellDone()
{
Student myHero = Array.Find(enrolled,
(Student alpha) => (alpha.firstExam < 65 && alpha.finalExam > 85));
if (myHero != null)
{
myHero.print();
System.Console.WriteLine("Watch 'em as they go!");
}
}
}


Where the argument list of our lambda expression is found inside the parentheses to the left of our => notation, and the code of our expression found to the right. Note: I don't have to include curly braces here, only because there's exactly one line of code being executed (a perfect setup for when to use lambda expressions at all). The parentheses I use on the right side are only there as a personal preference, to help me see the compound relational expression being used. If I had more instructions to be executed, I would need to include curly braces and semi-colons, like I would for any other body of code. Such as:

Predicate<Student> myPredicate = (Student alpha) =>
{
System.Console.WriteLine("I don't know what all to do here.");
System.Console.WriteLine("But I'm doing more than one thing.");
};


You can sometimes get away without defining the data type of the argument, which means you should probably always define the data type whenever possible. You can also specify for lambda expressions to take no arguments with empty parentheses ().