Generic delegates
Before exploring this topic, it is recommended that you familiarize yourself with the following topics:
- The concept of delegate. Declaration of delegate type. Using a delegate in the program. Group transformation of methods
- Generics. Basic concepts. Generic classes and structures
Contents
- 1. Generalized delegates. Features of use. Syntax for declaring a generic delegate for multiple types
- 2. Syntax for declaring a generic delegate for one type T
- 3. An example of a generic delegate that takes one type T as a parameter
- 4. An example of a generic delegate that takes two types T1, T2 as parameters
- 5. An example of declaring and using generic delegate that is consistent with static methods
- Related topics
Search other resources:
1. Generalized delegates. Features of use. Syntax for declaring a generic delegate for multiple types
C# allows the use of generic delegates that receive generic types as parameters. The advantage of generic delegates is that a typed generic form of a method is created, which is then matched to a specific method of any class. A method that matches a generic delegate must have a similar signature. Concrete methods can be either static methods or instance methods.
Generic delegates allow you to safely call any method that conforms to its generic form.
The general form of declaring a generic delegate is as follows:
delegate return_type DelegateName<T1, T2, ..., TN>(arguments_list);
here
- DelegateName – the name of the generic delegate;
- T1, T2, TN – the names of the types that the delegate operates on;
- arguments_list – the list of arguments that the delegate receives.
After such a declaration, you can create a reference to a generic delegate in the following form:
DelegateName<T1, T2, ..., TN> refDelegate<type1, type2, ..., typeN>;
here
- DelegateName<T1, T2, …, TN> – type name of generic delegate;
- refDelegate – the name of the generic delegate reference;
- type1, type2, typeN – names of types declared in the program or names of basic types (int, char, string, etc.).
If a reference is declared, then this reference can be assigned the name of a compatible method something like this:
refDelegate = obj.MethodName;
here
- obj – the name of the instance of the class containing the MethodName() method;
- MethodName – the name of the method that is compatible with the DelegateName delegate. Compatibility means that the number and types of parameters for a method and a delegate are the same.
After the reference points to the method, it is possible to call this method in the usual way.
refDelegate(arguments_list);
here
- arguments_list – a list of arguments passed to the MethodName() method, which is called by refDelegate.
⇑
2. Syntax for declaring a generic delegate for one type T
If a delegate is declared for only one generic type T, then the general form of such a declaration is as follows
delegate return_type DelegateName<T>(arguments_list);
here
- DelegateName – the name of generic delegate;
- T – the name of the generic delegate type;
- arguments_list – the list of arguments that the delegate receives.
Accordingly, the declaration of a reference to the delegate DelegateName<T> and its use can be as follows
refDelegate = obj.MethodName; ... refDelegate(arguments_list);
here
- refDelegate – a reference to the delegate DelegateName<T>;
- arguments_list – a list of arguments passed to the MethodName method.
⇑
3. An example of a generic delegate that takes one type T as a parameter
The example declares a generic delegate Equal<T> that operates on type T and receives two parameters of type T. The delegate returns a bool value that determines the equality (inequality) of the two received parameters.
The EqualOperations class is also declared, which contains the implementation of the EqualInt(), EqualShort(), and EqualString() methods. These methods determine equality for int, short, and string, respectively. The methods are compatible with the Equal<T> delegate type.
using System; namespace ConsoleApp19 { // Generic delegate delegate bool Equal<T>(T value1, T value2); // A class containing methods that are compatible with the Equal<T> delegate class EqualOperations { // For int type public bool EqualInt(int value1, int value2) { return value1 == value2; } // For short type public bool EqualShort(short value1, short value2) { return value1 == value2; } // For string type public bool EqualString(string value1, string value2) { return value1 == value2; } } class Program { static void Main(string[] args) { // 1. Declare an instance of the EqualOperations class EqualOperations obj = new EqualOperations(); // 2. Using delegate for int type // 2.1. Construct a delegate named delInt for type int Equal<int> delInt = obj.EqualInt; // 2.2. Call method using delegate for int type bool equalInt = delInt(5, 5); Console.WriteLine("equalInt(5,5) = {0}", equalInt); // 3. Using a delegate for the string type // 3.1. Construct a delegate named delString Equal<string> delString = obj.EqualString; // 3.2. Call a method using delegate for the string type bool equalString = delString("bestprog.net", "bestprog"); Console.WriteLine("equalString = {0}", equalString); Console.ReadKey(); } } }
The result of the program
equalInt(5,5) = True equalString = False
⇑
4. An example of a generic delegate that takes two types T1, T2 as parameters
The example declares a delegate using two types T1, T2.
using System; namespace ConsoleApp19 { // Delegate using two types T1, T2 delegate void Operation<T1, T2>(T1 value1, T2 value2); // A class containing a method that agrees with the Operation<T1, T2> delegate class Methods { public void Print(int value1, double value2) { Console.WriteLine("value1 = {0}", value1); Console.WriteLine("value2 = {0}", value2); } } class Program { static void Main(string[] args) { // Declare an instance of the Methods class Methods obj = new Methods(); // Declare a reference to the delegate Operation<T1, T2> Operation<int, double> refOp; // Assign the address of the Print() method to refOp refOp = obj.Print; // Call the Print() method using refOp reference refOp(23, 8.89); Console.ReadKey(); } } }
The result of the program
value1 = 23 value2 = 8.89
⇑
5. An example of declaring and using generic delegate that is consistent with static methods
A generic delegate can be applied to static methods. The example declares a delegate to ensure compatibility with static methods that implement finding the minimum value for the int and double types. The main() function demonstrates the use of the Min<T> delegate.
using System; namespace ConsoleApp19 { // Generic delegate that receives an array of generic type T // and returns the value of type T delegate T Min<T>(T[] array); // A class containing methods for finding the minimum value // in an array for different numeric types class MinValues { // Finding the minimum value in an array of type double public static double GetMinDouble(double[] array) { double min = array[0]; for (int i = 1; i < array.Length; i++) if (min > array[i]) min = array[i]; return min; } // For type int public static int GetMinInt(int[] array) { int min = array[0]; for (int i = 1; i < array.Length; i++) if (min > array[i]) min = array[i]; return min; } } class Program { static void Main(string[] args) { // 1. Using the Min<T> delegate for the double type. // 1.1. Declare a testable array of type double double[] AD = { 2.3, 2.5, 1.8, 1.1, 2.8, 1.9 }; // 1.2. Declare a reference to the Min<T> delegate for type double Min<double> refDouble; // 1.3. Assign a static method to the reference refDouble = MinValues.GetMinDouble; // 1.4. Call the GetMinDouble() method by reference refDouble double minDouble = refDouble(AD); Console.WriteLine("minDouble = {0}", minDouble); // 2. Using a delegate for int type // 2.1. Declare the array under test int[] AI = { 22, 33, 13, 18, 19, 140, 18, 10, 134 }; // 2.2. Declare a reference to the Min<T> delegate for type int // and assign the static GetMinInt method to it Min<int> refInt = MinValues.GetMinInt; // 2.3. Call the GetMinInt method by reference refInt int minInt = refInt(AI); Console.WriteLine("minInt = {0}", minInt); Console.ReadKey(); } } }
After starting the program will give the following result
minDouble = 1.1 minInt = 10
⇑
Related topics
- The concept of delegate. Declaration of delegate type. Using a delegate in the program. Group transformation of methods
- Generics. Basic concepts. Generic classes and structures
- Generic interfaces. Declaration syntax. Implementing generic interfaces in classes. Examples
- Generic methods in classes. Declaration syntax. Methods call
⇑