深入解析C#编程中泛型委托的使用
在看泛型委托之前还需要先了解委托的概念。
这里讲的委托有两种类型一种是有返回值的,另一种是事件委托。
//定义有返回值的委托 publicdelegatestringGenricDelegate<T,S>(Ttitle,Sauthor); //定义事件委托。 publicdelegatevoidGenricDelegateEnent<E,P>(EName,PAddress); publicclassGenericDelegateClass<V,F> { //声明委托 publicGenricDelegate<V,F>GdeleValue; //声明事件委托 publiceventGenricDelegateEnent<V,F>GdEvent=null; publicstringGetValues(Vtitle,Fauthor) { //调用委托 returnGdeleValue(title,author); } publicGenericDelegateClass() { } publicvoidInvokeEvent(Vname,Faddress) { if(GdEvent!=null) { //调用委托 GdEvent(name,address); } } }
上面我们定义及调用了泛型委托,接下来就来梆定委托。
privatevoidbtnDelegate_Click(objectsender,EventArgse) { GenericDelegateClass<string,string>gd=newGenericDelegateClass<string,string>(); //将DelegateReturn事件梆定给GdeleValue gd.GdeleValue=newGenricDelegate<string,string>(DelegateReturn); //将GenericEvent事件梆定给GdEvent gd.GdEvent+=newGenricDelegateEnent<string,string>(GenericEvent<string,string>); } publicstringDelegateReturn<T,S>(Ttitle,Sauthor) { returntitle.ToString()+author; } privatevoidGenericEvent<V,F>(Vname,Faddress) { // }
在这里我们看到我在梆定DelegateReturn的时候并没有带泛型参数。在这里的泛型参数其实是没什么意义的。因为他的类型取决于调用委托的方法的类型。也就是在前面那段代码中InvokeEvent方法的类型,这里的DelegateReturn要用泛型方法是可以随时跟InvokeEvent的参数类型保持一至。这样梆定后我们再来调用gd.GetValues("mygenericpost","fastyou");这样调用的其实就是DelegateReturn的方法,这就是委托的好处了,同样调用gd.InvokeEvent("mygenericpost","fastyou");就是GenericEvent方法。
委托可以定义自己的类型参数。引用泛型委托的代码可以指定类型参数以创建已关闭的构造类型,就像实例化泛型类或调用泛型方法一样,如下例所示:
publicdelegatevoidDel<T>(Titem); publicstaticvoidNotify(inti){} Del<int>m1=newDel<int>(Notify);
C#2.0版具有称为方法组转换的新功能,此功能适用于具体委托类型和泛型委托类型,并使您可以使用如下简化的语法写入上一行:
Del<int>m2=Notify;
在泛型类内部定义的委托使用泛型类类型参数的方式可以与类方法所使用的方式相同。
classStack<T> { T[]items; intindex; publicdelegatevoidStackDelegate(T[]items); }
引用委托的代码必须指定包含类的类型变量,如下所示:
privatestaticvoidDoWork(float[]items){} publicstaticvoidTestStack() { Stack<float>s=newStack<float>(); Stack<float>.StackDelegated=DoWork; }
根据典型设计模式定义事件时,泛型委托尤其有用,因为发送方参数可以为强类型,不再需要强制转换成Object,或反向强制转换。
delegatevoidStackEventHandler<T,U>(Tsender,UeventArgs); classStack<T> { publicclassStackEventArgs:System.EventArgs{} publiceventStackEventHandler<Stack<T>,StackEventArgs>stackEvent; protectedvirtualvoidOnStackChanged(StackEventArgsa) { stackEvent(this,a); } } classSampleClass { publicvoidHandleStackChange<T>(Stack<T>stack,Stack<T>.StackEventArgsargs){} } publicstaticvoidTest() { Stack<double>s=newStack<double>(); SampleClasso=newSampleClass(); s.stackEvent+=o.HandleStackChange; }