Whereas passing objects as arguments is an ordinary and acquainted method to invoke strategies, offering strategies as arguments to different strategies is much less so. Nonetheless, we frequently should cross a technique as a parameter to a different technique when working with occasion dealing with in C#. We do that utilizing delegates.
I offered an summary of delegates in an earlier article right here. On this article, we’ll study how we are able to work with Motion, Func, and Predicate delegates in C#. To work with the code examples offered on this article, it is best to have Visible Studio 2022 put in in your system. Should you don’t have already got a duplicate, you’ll be able to obtain Visible Studio 2022 right here.
A delegate is a type-safe perform pointer that may reference a technique that has the identical signature as that of the delegate. Delegates are used to outline callback strategies and implement occasion dealing with, and they’re declared utilizing the “delegate” key phrase. You may declare a delegate that may seem by itself and even nested inside a category.
What are Func and Motion delegates? How can they be used?
The most typical delegates in C# are the Func delegate and the Motion delegate. Each are reference varieties that encapsulate a technique. The Func delegate factors to a technique that accepts parameters and returns a price; the Motion delegate factors to a technique that accepts parameters however doesn’t return a price (i.e., returns void).
Each of those delegate objects will take zero or many parameters, and we are able to use them with lambda expressions or nameless strategies.
The syntax for creating an motion delegate in C# is
Motion<TParameter>
We will create an Motion delegate in C# utilizing the Motion key phrase.
Motion<string> actionDelegate = new Motion<string>(DisplayText);
actionDelegate("Hey World!");
The syntax for declaring a Func delegate in C# is
Func<TParameter, TOutput>
To create a perform delegate in C#, we use the Func key phrase.
public class DelegateHelper
{
Func<double, double> functionDelegate = new Func<double, double>(GetTax);
public static double GetTax(double netSalary)
{
return (double)(netSalary * .3);
}
}
Console.WriteLine(DelegateHelper.GetTax(100000));
Right here the DelegateHelper class comprises a static technique named GetTax, which calculates and returns tax primarily based on web wage, and a delegate that factors to this technique. A Func delegate has been used to invoke the GetTax technique.
Utilizing Motion delegates in C#
The next code itemizing supplies one other instance of how you should utilize an Motion delegate. This code snippet when executed would print the phrase “Hey!!!” within the console window.
static void Major(string[] args)
{
Motion<string> motion = new Motion<string>(Show);
motion("Hey!!!");
Console.Learn();
}
static void Show(string message)
{
Console.WriteLine(message);
}
Utilizing Func delegates in C#
And here’s a second instance of utilizing a Func delegate in C#. The next code snippet prints the worth of a well being reimbursement account, or HRA (calculated as 40% of primary wage). The bottom wage is handed to the delegate as an argument.
static void Major(string[] args)
{
Func<int, double> func = new Func<int, double>(CalculateHra);
Console.WriteLine(func(50000));
Console.Learn();
}
static double CalculateHra(int primary)
{
return (double)(primary * .4);
}
Observe that the second parameter within the declaration of the Func delegate within the code snippet given earlier represents the return sort of the strategy to which the delegate would level. On this instance, the calculated Hra worth is returned as double.
Utilizing Predicate delegates in C#
A Predicate is a delegate that accepts a number of generic parameters and returns a boolean worth. Predicate delegates are sometimes used to carry out search operations primarily based on a set of standards.
Right here is the syntax for a Predicate delegate.
Predicate<T>
Observe that Predicate<T> is mainly equal to Func<T,bool>.
Think about the next entity class named Buyer.
class Buyer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Tackle { get; set; }
public string Metropolis { get; set; }
public string State { get; set; }
public string Nation { get; set; }
}
Subsequent, create an inventory of shoppers and retailer objects of sort Buyer into it.
Record<Buyer> custList = new Record<Buyer>();
custList.Add(new Buyer { Id = 1, FirstName = "Joydip", LastName = "Kanjilal", State = "Telengana", Metropolis = "Hyderabad", Tackle = "Begumpet", Nation = "India" });
custList.Add(new Buyer { Id = 2, FirstName = "Steve", LastName = "Jones", State = "OA", Metropolis = "New York", Tackle = "Lake Avenue", Nation = "US" });
The next is the whole code itemizing that exhibits how we are able to use a Predicate delegate to go looking information.
static void Major(string[] args)
{
Record<Buyer> custList = new Record<Buyer>();
custList.Add(new Buyer { Id = 1, FirstName = "Joydip", LastName = "Kanjilal", State = "Telengana", Metropolis = "Hyderabad", Tackle = "Begumpet", Nation = "India" });
custList.Add(new Buyer { Id = 2, FirstName = "Steve", LastName = "Jones", State = "OA", Metropolis = "New York", Tackle = "Lake Avenue", Nation = "US" });
Predicate<Buyer> hydCustomers = x => x.Id == 1;
Buyer buyer = custList.Discover(hydCustomers);
Console.WriteLine(buyer.FirstName);
Console.Learn();
}
When the above code snippet is executed, the title “Joydip” will likely be displayed within the console window.
Utilizing variance in delegates in C#
If you outline your delegates, you should utilize covariance and contravariance to present your delegate a higher degree of flexibility. The covariance method makes it doable for a technique to return a extra derived sort than that outlined within the delegate. Utilizing contravariance, you’ll be able to outline a technique that accepts much less derived arguments than these within the delegate sort.
The next code snippet illustrates covariance in delegates.
class TypeA {}
class TypeB : TypeA {}
public delegate TypeA MyDelegate();
public static TypeA HandlerA()
{
//Some code
}
public static TypeB HandlerB()
{
//Some code
}
MyDelegate delegateA = HandlerA;
MyDelegate delegateB = HandlerB;
Now, take into account the next two delegate declarations.
public delegate void KeyEventHandler(object sender, KeyEventArgs e)
public delegate void MouseEventHandler(object sender, MouseEventArgs e)
As a result of EventArgs is the bottom class of each KeyEventArgs and MouseEventArgs, you’ll be able to benefit from contravariance to mix them into only one handler that’s able to dealing with each key and mouse occasions as proven within the code snippet given under.
non-public void MyCommonHandler(object sender, System.EventArgs e)
{
//Some code
}
Delegates are among the many most generally used options of the C# programming language. They’re ideally suited to implementing event-driven programming. Most often, the return sort of the strategy pointed to by a delegate should be equivalent to the sort specified within the delegate’s declaration. Nevertheless, we are able to flip to covariance and contravariance to realize extra flexibility.
Copyright © 2023 IDG Communications, Inc.