C# 委托 灰太狼 2023-06-18 10:57 1阅读 0赞 对于C\#中的委托,我之前也用过很多次,但是总是感觉缺了点什么,对它有点朦胧感。所以就搜集了一下资料整理了一下思路,做了这一篇学习的笔记。 ## 1.委托的构成 ## 对于C\#来讲,委托的算是C\#“创始人”之一了,因为它在C\#1.0时就已经存在了,而且还是C\#语言的“大股东”。相信对于用过C\#委托的人(包括我),对委托都有一个直观概念,只是无法表达出来,说白了就是知其然不知其所以然。所以为了让自己好受一点,就只能梳理一下自己的思路,先按照自己的思路来理解一下委托,只是保证不了对错。 如果和我一样之前学过一点C++的人,看到委托第一个想到的就是“函数指针”。因为他们两者的作用很是相似,都是可以通过他们来调用方法(函数)。但是委托和函数指针还是有所区别的,在下面我会谈到一点(因为我了解的也比较有限)。 我们都能很直观的感受到“程序世界”就是在模仿着“真实世界”在一直往前发展着,那么我们以真实世界来理解委托可能会更容易理解委托。 实例:假如你是一个快死的人(这也是一本书上的例子),你有一份比较大的家业,那么你肯定就要立一份遗嘱来安排一下后事。这时你就需要找一个律师来等你死后来执行遗嘱中的内容,也就是要把遗嘱“委托”给律师。 从上述的例子中我们可以很容易的总结出委托的构成: 1、声明一个委托类型,在例子中就是指律师行业,这用于找到一个律师 2、必须要创建一个委托实例,也就是找到了一个律师 3、必须要有一个要执行的方法,也就是遗嘱 4、调用委托实例,也就是律师在你死后要执行遗嘱中的内容 ## 2.委托的使用 ## 以上面的思路我们可以很容易的实现该委托,如下所示: class Program { static void Main(string[] args) { Lawer lawer; //创建一个委托实例,也就是找到了一个律师 lawer = Testament; //把遗嘱交给律师 //Lawer lawer=new Lawer(Testament); //使用这种方式也可以 lawer(); //律师执行遗嘱中的内容 Console.ReadKey(); } static void Testament() //遗嘱 { Console.WriteLine("I have no money!!!"); } } delegate void Lawer(); //声明一个委托类型,其声明格式类似于函数指针的声明格式,要找一个律师行业的人 ![在这里插入图片描述][20191202094416357.png] 程序很简单,但是正所谓麻雀虽小五脏俱全,我们可以很容易的看出委托的级别和类是相同的,而且其声明定义和类完全一样。这中间好像存在点联系,我们按出现时间来想一下就可以明白了,是类先出现还是委托先出现呢?肯定是类。说类是我们编程的基本单位这一点不过分吧,但是突然出现了一个委托而且级别和用法与类都有些相似,这不免让人把委托向类这上面去想。事实上,有一些书上确实说明了其实委托就是一种特殊的“类”。 为了简化我们对委托的编码,还有就是防止我们随意的定义委托类型,微软很贴心的在.NET框架中内置了已经定义好的泛型委托Func<>(有返回值),Action<>(无返回值),因此上述代码可改为: class Program { static void Main(string[] args) { Action lawer=new Action(Testament); //创建一个委托实例,也就是找到了一个律师,并把遗嘱交给律师 //lawer = Testament; //把遗嘱交给律师 lawer(); //律师执行遗嘱中的内容 Console.ReadKey(); } static void Testament() //遗嘱 { Console.WriteLine("I have no money!!!"); } } //delegate void Lawer(); //声明一个委托类型,要找一个律师行业的人 现在委托看起来是不是更像是一个类了,Testament方法现在只不过是一个参数而已。我们还有更直接的方式来看一下委托是一种类,如下所示: 第一种方式: Type t = typeof(Action); //获取委托的数据类型 Console.WriteLine(t.IsClass); //判断委托是不是类 ![在这里插入图片描述][20191202152654413.png] 第二种方式: 我们将上述程序生成的.exe文件使用反编译器进行反编译再来查看一下代码,如下图所示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RheXVoYWl0YW5nMQ_size_16_color_FFFFFF_t_70]![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RheXVoYWl0YW5nMQ_size_16_color_FFFFFF_t_70 1] 从上也可以看出,我们定义委托类型产生的类还包含4个方法:分别是构造函数、BeginInvoke()、EndInvoke()和Invoke()。 [MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)] public Lawer(object @object, IntPtr method); [MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)] public virtual IAsyncResult BeginInvoke(AsyncCallback callback, object @object); [MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)] public virtual void EndInvoke(IAsyncResult result); [MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)] public virtual void Invoke(); 遗嘱代码中lawer()其实是调用了委托中的Invoke()方法,也就是说lawer()=lawer.Invoke()。 ## 3.委托与函数指针 ## 我们都知道C++语言在众多语言中是少数有着极为强大的操作计算机的能力,这也是其几十年一直屹立不倒的原因,也从这可以看出C++其最大的优势就在于:直接操纵内存,但这却也是C++最大的缺点因此这也直接导致了日后Java的出现。这是因为直接操纵计算机内存存在着很大的风险,对于开发人员尤其致命。 C\#相较于Java都要晚了将近4年,那它所定义的“委托”就是要弥补C++函数指针的不足(直接操纵内存),因此我们可以把委托看做是函数指针的一个升级版,而两者很大的一个区别就在于“安全性”。这主要体现C\#中已经很少采用“指针”来让用户直接操纵计算机内存,而是使用委托(类)这种引用类型来间接达到之前函数指针的功能。 ## 4.小结 ## **委托是一种类,可以把委托看做是函数指针的升级版,其使用方法与函数指针颇为像似并且其作用的对象也为函数,类似于C++中重载了“()”操作符的类。** 最后就是对于委托的认知我大部分都是从书上和视频中得到的,以我现在的能力(毕竟只是个小白)只能做到“管中窥豹”,从我所得到的所有信息中整理出来这篇学习笔记,如有错误还请见谅。 > 参考资料:《C\# in depth》、《C\#入门详解》视频 [20191202094416357.png]: https://img-blog.csdnimg.cn/20191202094416357.png [20191202152654413.png]: https://img-blog.csdnimg.cn/20191202152654413.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RheXVoYWl0YW5nMQ_size_16_color_FFFFFF_t_70]: https://img-blog.csdnimg.cn/2019120216210723.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RheXVoYWl0YW5nMQ==,size_16,color_FFFFFF,t_70 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RheXVoYWl0YW5nMQ_size_16_color_FFFFFF_t_70 1]: https://img-blog.csdnimg.cn/20191202162302967.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RheXVoYWl0YW5nMQ==,size_16,color_FFFFFF,t_70
还没有评论,来说两句吧...