zoukankan      html  css  js  c++  java
  • [C#参考]委托机制

    1. 委托概述

    这是一个新的概念,但是其本质并不是什么新鲜的事物,委托本质上就是一个类。只不过一般的类是数据的集合,委托保存的是一个或者多个方法。委托是引用类型,因此委托有引用和对象,同时委托对象中包含指向方法的引用,也就是C++中的函数指针的概念。也就是说委托中的数据成员都是一些函数指针,这些函数指针指向的方法和委托类型有相同的函数签名。

    从上图中可以看出,委托和类基本上就是一个东西,过程都是一样的:

    声明一个类型->声明该类型的引用变量(在栈中)->利用new在堆中创建实例对象,同时利用构造函数传参数,只不过委托实例利用默认的构造函数初始化调用列表->使用变量,通过引用变量,使用该类型的对象。

    类对象的数据部分保存的是一般的数据类型 ,委托对象的数据部分保存的是函数指针,这些函数指针挨着盘的存放,构成了调用列表

    2. 声明委托类型

    委托是类型,就好像类是类型一样,所以委托类型必须在被用来创建引用变量以及类型的对象之前声明。

    delegate void MyDel(int x);
    //其中的MyDel就是委托类型名,类似于类名

    注意:委托的类型声明,不需要在类内部声明,因为委托类型和类是同一个级别的。

    3. 创建委托对象

    委托是引用类型的,因此有引用和对象,就像上图中所示,引用变量存在栈内存中,委托对象存在堆内存中。

    MyDel delVar;
    //委托变量的声明,也就是委托引用

    委托对象的创建:

    delVar = new MyDel(myIntsObj.methodName);
    dVar = new Mydel(SClass.staticMethodName);
    //使用new关键字创建委托对象,同时给委托类型的默认构造函数传一个方法名作为参数。
    //这个方法名就是委托对象调用列表中的第一个成员的方法的名字。

    提示:在创建委托对象的时候有快捷的语句

    delVar = myIntsObj.methodName;
    dVar   = SClass.staticMethodName;
    

      这是因为方法名称和其相对应的委托类型之间有隐式的转换。

    图中的Invocation list里面存储的都是一些函数指针。

    当然上面的创建对象可以在一条语句上完成:

    MyDel delVar = new MyDel(myIntsObj.methodName);
    MyDel dVar   = new Mydel(SClass.staticMethodName);
    

    或者:

    MyDel delVar = myIntsObj.methodName;
    MyDel dVar   = SClass.staticMethodName;
    

    4. 委托赋值

    由于委托是引用类型的,可以通过给它赋值来改变包含在委托变量中的引用。旧的委托对象会被垃圾回收器回收。

    MyDel delVar;
    
    delVar = myIntsObj.methodName;
    .
    .
    delVar   = SClass.staticMethodName;
    

      

    注意:这里用到了C#垃圾回收器的知识。

    5. 修改委托

    事实上,委托是恒定的,委托对象被创建后就不会再改变。任何对委托对象的修改都是创建一个新的委托,同时按照要求修改这个新委托对象的调用列表。

    组合委托:

    MyDel delA = myIntsObj.methodName;
    MyDel delB = SClass.staticMethodName;
    MyDel delC = delA + delB;//组合调用列表

    委托增加和删除方法:

    MyDel delVar = inst.MyM1;//创建并初始化
    delVar += SCL.m3;//增加方法
    delVar += X.Act;//增加方法
    

      

    delVar -= SCL.m3;//从委托移除方法
    

      

    6. 调用委托

    试图调用空的委托对象会抛出异常,所以每次调用委托对象的时候,把委托对象和null进行比较,来判断委托对象的调用列表是否为空。

    注意:

    委托引用变量没有被初始化前,委托引用是null。委托对象中的调用列表为空,那么委托引用也为null。

    调用方法是直接用委托引用,加上相对应的参数:

    if(delVar != null)
    {
    	delVar(55);
    }
    

      

    补充的知识点:

    1. 当调用带返回值的委托对象时,调用列表中最后一个方法返回的值就是委托调用的返回值,调用列表中其他所有的方法的返回值都会被忽略。只是返回值被忽略,方法的操作还是有效果的(比如对全局变量的修改)。

    2. 如果委托有引用参数,参数值会根据调用列表中的一个或多个方法的返回值而改变。在调用委托列表中的下一个方法时,参数的新值(不是初始值)会传给下一个方法。

  • 相关阅读:
    UML用例图
    directX--大约CSource和CSourceStream (谁在叫fillbuffer)
    【云】如何建立微信在全国卖场地图?
    C++ Primer 学习笔记_38_STL实践与分析(12)--集成的应用程序容器:文本查询程序
    Android使用SVG矢量创建很酷的动态效率!
    观察者模式(observer行为)c#简单的例子
    Oracle MySQL
    tomcat 跨域
    Jms Spring
    Ehcache使用
  • 原文地址:https://www.cnblogs.com/stemon/p/4431534.html
Copyright © 2011-2022 走看看