Before looking at generic delegates, you also need to understand the concept of delegates first.
There are two types of delegates mentioned here: one has a return value, and the other is event delegates.
//Define a delegate with a return value public delegate string GenricDelegate<T, S>(T title, S author); //Define event delegate. public delegate void GenricDelegateEnent<E,P>(E Name,P Address); public class GenericDelegateClass<V,F> { //Declare the delegation public GenricDelegate<V, F> GdeleValue; //Declare the event delegation public event GenricDelegateEnent<V, F> GdEvent = null; public string GetValues(V title, F author) { //Calling the delegate return GdeleValue(title, author); } public GenericDelegateClass() { } public void InvokeEvent(V name, F address) { if (GdEvent != null) { //Calling the delegate GdEvent(name, address); } } }
We have defined and called the generic delegation above, and then we will come to Bangding delegation.
private void btnDelegate_Click(object sender, EventArgs e) { GenericDelegateClass<string, string> gd = new GenericDelegateClass<string, string>(); //Determine the DelegateReturn event to GdeleValue = new GenricDelegate<string, string>(DelegateReturn); //Determine the GenericEvent event to GdEvent += new GenricDelegateEnent<string, string>(GenericEvent<string,string>); } public string DelegateReturn<T,S>(T title,S author) { return () + author; } private void GenericEvent<V, F>(V name, F address) { // }
Here we see that when I was in Bangding DelegateReturn, I did not take generic parameters. The generic parameters here are actually meaningless. Because its type depends on the type of the method invoked. That is, the type of the InvokeEvent method in the previous code. The DelegateReturn here needs to be used as a generic method, which can be kept to the same parameter type as the InvokeEvent at any time. After this, we call ("my generic post","fastyou"); the call in this way is actually the DelegateReturn method, which is the benefit of delegate. Also, call ("my generic post","fastyou"); is the GenericEvent method.
Delegate can define its own type parameters. Code that references generic delegates can specify type parameters to create a closed constructor type, just like instantiating a generic class or calling a generic method, as shown in the following example:
public delegate void Del<T>(T item); public static void Notify(int i) { } Del<int> m1 = new Del<int>(Notify);
Version C# 2.0 has a new feature called method group conversion, which works for specific delegate types and generic delegate types and allows you to write to the previous line using the simplified syntax below:
Del<int> m2 = Notify;
The way the delegate defined inside a generic class uses generic class type parameters can be used in the same way the class method is used.
class Stack<T> { T[] items; int index; public delegate void StackDelegate(T[] items); }
The code that references the delegate must specify a type variable containing the class, as shown below:
private static void DoWork(float[] items) { } public static void TestStack() { Stack<float> s = new Stack<float>(); Stack<float>.StackDelegate d = DoWork; }
Generic delegates are especially useful when defining events based on typical design patterns, because the sender parameters can be strongly typed and no longer need to be cast to Object, or reverse cast.
delegate void StackEventHandler<T, U>(T sender, U eventArgs); class Stack<T> { public class StackEventArgs : { } public event StackEventHandler<Stack<T>, StackEventArgs> stackEvent; protected virtual void OnStackChanged(StackEventArgs a) { stackEvent(this, a); } } class SampleClass { public void HandleStackChange<T>(Stack<T> stack, Stack<T>.StackEventArgs args) { } } public static void Test() { Stack<double> s = new Stack<double>(); SampleClass o = new SampleClass(); += ; }