委托也可以泛型化,也就是委托也定义自己的类型参数,这样的委托称为泛型委托。在使用委托的代码中可以给委托指定类型参数的具体类型,而让泛型委托实例化为具体的委托实例。就像实例化泛型类或调用泛型方法一样。
定义一个泛型委托的语法格式:
[public|private|protected] delegate 返回类型 委托名<类型参数列表>(参数列表)
例如public delegate void Del<T>(T item);该委托表示了一个返回void类型,而且参数的类型是T的函数或者方法。
实例化泛型委托并与函数或者方法绑定。比如,现在有一个方法
public static void Notify(int i) { },那么Del<int> m1 = new Del<int>(Notify);就是生成了一个Del<int>类型的委托m1,该委托代表了方法Notify。
泛型委托的调用:m1(1) ;该委托的调用与实际调用方法Notify(1)效果一样。注意在实例化泛型时,一定要给泛型委托指明类型参数的具体类型。该类型应该与委托所代表的方法或者函数的参数的类型相互对应。
例子GenericsDelegate演示了一个泛型委托的定义,实例化,绑定,调用的完整过程。例子中类ProvideMethod专门提供了两个参数类型不相同的两个方法,在测试代码中演示了完整的过程。
类ProvideMethod的代码
namespace GenericsDelegate
{
class ProvideMethod
{
public void MethodID(int i, double d)
{
Console.WriteLine("方法的参数类型是int与double");
}
public void MethodCS(char c, string s)
{
Console.WriteLine("方法的参数类型是char与string");
}
}
}
泛型委托的测试代码
namespace GenericsDelegate
{
//定义一个泛型委托
public delegate void MyDelegate<T,U>(T t,U u);
class Program
{
static void Main(string[] args)
{
ProvideMethod p = new ProvideMethod();
//实例化泛型委托,并绑定一个相对应的方法
MyDelegate<int, double> IDDelegate = new MyDelegate<int, double>(p.MethodID);
MyDelegate<char, string> CSDelegate = new MyDelegate<char, string>(p.MethodCS);
//委托调用
IDDelegate(3, 4.5);
CSDelegate('a', "string");
Console.ReadKey();
}
}
}
在泛型类内部定义的委托使用泛型类类型参数的方式可以与类方法所使用的方式相同。
class Stack<T>
{
T[] items;
int index;
public delegate void StackDelegate(T[] items);
}
那么在使用这个委托时,必须指定包含类的类型变量,否则这个委托所能够代表的方法或者函数的类型就不能确定。如下所示:
private static void DoWork(float[] items) { }
public static void TestStack()
{
Stack<float> s = new Stack<float>();
Stack<float>.StackDelegate d = DoWork;
}
提起委托,就不能不说事件,事件与委托就像一对孪生兄弟。既然有泛型委托,那么也应该有泛型事件。泛型事件在某些应用中比较重要。因为在以前,事件处理函数的发送方参数的类型总是Object。因此事件处理函数没有办法根据不同的发送者身份或者类型对事件进行不同的处理。现在如果使用泛型事件就可以使用强类型的发送方,不再需要强制转换成Object或反向强制转换。而且也可以根据发送方类型的不同对消息进行不同的处理。
例子GenericsEvent中演示了发送方是强类型的情况,在这个例子中依然使用泛型类Publisher<T>来表示消息的发布者,用类Receiver来表示消息的订阅者。
消息发布者类Publisher<T>的代码
namespace GenericsEvent
{
public class Publisher<T>
{
//定义了一个泛型事件,该事件的发布者的类型是强类型
public event MyEventHandler<T> Click;
//发送事件函数
public void SendMessage()
{
Click(this);
}
}
}
消息订阅者类Receiver的代码
namespace GenericsEvent
{
class Receiver
{
//事件处理函数,该函数具有强类型的参数表示发送者
public void OnClick(Publisher<int> sender)
{
Console.WriteLine("该事件已经写入日志文件");
}
//事件处理函数
public void OnClick(Publisher<double> sender)
{
Console.WriteLine("该事件已经发送到主管信箱");
}
}
}
测试代码
namespace GenericsEvent
{
//定义了一个泛型委托,该委托指定了发送者的具体类型
public delegate void MyEventHandler<T>(Publisher<T> Sender);
class Program
{
static void Main(string[] args)
{
//事件发布者
Publisher<int> publisherI = new Publisher<int>();
Publisher<double> publisherD = new Publisher<double>();
//事件订阅者
Receiver receiver = new Receiver();
//开始绑定事件
publisherI.Click += receiver.OnClick;
publisherD.Click += receiver.OnClick;
//引发事件
publisherI.SendMessage();
publisherD.SendMessage();
Console.ReadKey();
}
}
}
程序的运行结果是
该事件已经写入日志文件
该事件已经发送到主管信箱
这样就可以根据发送消息者的身份对消息进行不同的处理了。