表面上看来使用delegate是一件很简单的事。
用delegate关键字定义,使用老套的new创建一个instance ,使用熟悉的方法调用写法调用,只不过不在是方法名,而是委托名。但是在这背后CLR为我们做了很多。当我们 写下下面这句话时public delegate void FeedBack(Int32 val);其实相当于 大概下面的代码(省略部分多线程相关代码)pubic class FeedBack:MulticastDelegate{ public FeedBack(Object object , IntPtr methodPtr) { xxxx } public virtual void Invoke(int32 val);}首先delegate 就是一个class。这个class会自动继承MuticastDelegate .然后,这个class 的构造函数就如上面所示,我们先看第二个参数 methodPtr 可以理解为函数的指针,或者说函数的地址。委托在真正运行的时候,就要找到这个函数的地址,并运行这个函数。对,我们要先找到这个函数的地址,对于 static类型的函数,地址是确定的,而对于实例函数而言,内部的函数地址则是不定的,它需要先确定具体的某个实例, 这既是第一个参数的用途,具体实例的引用,对于static类型的函数,就会默认传入一个null。其实,在基类 MutiCastDelegate中,有三个重要的非公开属性_target_methodPtr_invokationlist一二两个属性 刚好对应我们构造函数传入的两个参数,第三个属性和委托链有关,默认为null,我们先不讨论。也就是说:delegate 其实只是个wrapper ,包装着需要真正操作的对象 以及它的方法。public delegate void FeedBack <T>(T para); public delegate void FeedBack<Tint,Tstr>(Tint para1,Tstr para2); class 委托可以有泛型吗 { public static void Main(string[] args) { FeedBack<Int32 > fb = new FeedBack<int >(FeedBackInt); FeedBack<String > fb2 = new FeedBack<string >(FeedbackString); FeedBack<int ,string > fb3 = new FeedBack<int , string >(FeedbackIntString); fb.Invoke(2); fb2.Invoke( "haha"); fb3.Invoke(60,"haha" ); Console.ReadKey(); } public static void FeedBackInt(Int32 val) { Console.WriteLine(val); } public static void FeedbackString(String str) { Console.WriteLine(str); } public static void FeedbackIntString(int val,string str) { Console.WriteLine(val+":" +str); } }}
新闻热点
疑难解答