zoukankan      html  css  js  c++  java
  • C# 中委托的学习

     在C#中定义委托时要用关键字delegate ,名字自己起如:public delegate int BinaryOp(int x,int y);

      当C#编译器处理委托类型时,它先自动产生一个派生自System.MulticastDelegate的密封类。这个类与它的基类System.Delegate一起为委托提供必要的基础设施,以维护以后将要调用的方法的列表。如我们可以通过ildasm.exe来查看BinaryOp委托,如下:

    可见生成的BinaryOp类定义了3个公共方法:BeginEnvoke(); Invoke(),EndInvoke();其中Invoke()是核心方法;因为它被用来以同步方式调用委托对象维护的每个方法。这里的同步是指调用者必须等待调用完成才能继续执行。

    下面我们举个最简单的委托代码如下:

    View Code
     1 View Code 
     2 
     3 using System;
     4 using System.Collections.Generic;
     5 using System.Linq;
     6 using System.Text;
     7 
     8 namespace 委托学习
     9 {
    10     public delegate int BinaryOp(int x,int y);
    11     public class SimpleMath
    12     {
    13         public  int Add(int x,int y)
    14         {
    15             return x + y;
    16         }
    17         public static int Subtract(int x, int y)
    18         {
    19             return x - y;
    20         }
    21         public  void DisplayDelegateInfo(Delegate delObj)
    22         {
    23             foreach (Delegate d in delObj.GetInvocationList())
    24             {
    25                 Console.WriteLine("Method name is :{0}",d.Method);
    26                 Console.WriteLine("Type name is :{0}",d.Target);
    27             }
    28         }
    29     }
    30     class Program
    31     {
    32         static void Main(string[] args)
    33         {
    34             SimpleMath m = new SimpleMath();
    35             BinaryOp b = new BinaryOp(m.Add);
    36             Console.WriteLine("10+10={0}",b(10,10));
    37             Console.WriteLine("10+10={0}", b.Invoke(10, 10));
    38             m.DisplayDelegateInfo(b);
    39             Console.ReadKey();
    40         }
    41     }
    42 }

    运行结果:

    下面我们来看下有关委托的实例:

    有关概念:

    1. 支持多路委托:就是一个委托上绑定多个与委托定义相匹配的方法具体看如下例子;

    2. +=:就是向委托添加一个新的绑定方法;

    3. -= :同+=,只是把一个方法从委托上注销掉;

    4. 方法组转换:也就是当向注册函数添加委托变量时可以不写委托实例直接添加委托方法具体见实例代码;

    5. 委托协变 :当一个委托要求返回一个自定义类类型的时候,有可能我们一个类是继承的父类,但委托中要求返回的是父类类型,那我们就可以不用定义两个委托只定义一个返回类型为父类的委托,用这个委托来调用返回子类的方法,只不过在调用时用强制类型转换下就可以了如下代码;

    View Code
      1 View Code 
      2 
      3 using System;
      4 using System.Collections.Generic;
      5 using System.Linq;
      6 using System.Text;
      7 
      8 namespace 委托中级
      9 {
     10     public class Car
     11     { 
     12     //内部状态数据
     13         public int CurrentSpeed { get; set; }
     14         public int MaxSpeed { get;set;}
     15         public string PetName{get;set;}
     16 
     17         //汽车能用还是不能用
     18         private bool carIsDead;
     19 
     20         //类构造函数
     21         public Car()
     22         {
     23             MaxSpeed = 100;
     24         }
     25         public Car(string name,int maxSp,int currSp)
     26         {
     27             CurrentSpeed = currSp;
     28             MaxSpeed = maxSp;
     29             PetName = name;
     30         }
     31 
     32         //定义委托类型
     33         public delegate void CarEngineHander(string msgForCaller);
     34 
     35         //定义每个委托类型的成员变量
     36         private CarEngineHander listOfHanders;
     37 
     38         //向调用者添加注册函数
     39         //修改下使之支持多路广播,也就是把=变成+=
     40         public void RegisterWithCarEngine(CarEngineHander methodToCall)
     41         {
     42             //+=操作符实际上转换为一个对静态Delegate.Combine()方法的调用;我们可以从CIL中发现。
     43             listOfHanders += methodToCall;
     44         }
     45 
     46         //取消注册某方法
     47         public void UnRegisterWithCarEngine(CarEngineHander methodToCall)
     48         {
     49             listOfHanders -= methodToCall;
     50         }
     51         public void Accelerate(int delta)
     52         { 
     53         //如果汽车不能用,触发引爆事件
     54             if (carIsDead)
     55             {
     56                 if (listOfHanders != null)
     57 
     58                     listOfHanders("Sorry, this car is dead....");
     59             }
     60             else
     61             {
     62                 CurrentSpeed += delta;
     63 
     64 
     65                 //快不能用了吗
     66                 if (10 == (MaxSpeed - CurrentSpeed) && listOfHanders != null)
     67                 {
     68                     listOfHanders("Careful buddy! Gonna blow!");
     69                 }
     70                 if (CurrentSpeed >= MaxSpeed)
     71                     carIsDead = true;
     72                 else
     73                     Console.WriteLine("CurrentSpeed is : {0}.", CurrentSpeed);
     74             }
     75             }
     76         
     77     }
     78     public class SportCar : Car
     79     { 
     80     
     81     }
     82     class Program
     83     {
     84         static void Main(string[] args)
     85         {
     86             #region 委托的注册与Un注册
     87 
     88             Console.WriteLine("*****Delegate as event enablers*****");
     89             Car c = new Car("宝马", 100, 10);
     90 
     91             //还有个知识点就是方法组转换,也就是在注册事件中不引用如下的委托对象而是与其对应的方法如下 :
     92             //c.RegisterWithCarEngine(OnCarEngineEvent);
     93             c.RegisterWithCarEngine(new Car.CarEngineHander(OnCarEngineEvent));
     94             Car.CarEngineHander handler = new Car.CarEngineHander(OnCarEngineEvent2);
     95             c.RegisterWithCarEngine(handler);
     96             //c.RegisterWithCarEngine(new Car.CarEngineHander(OnCarEngineEvent2));
     97             Console.WriteLine("*****Speeding up*****");
     98             for (int i = 0; i < 6; i++)
     99             {
    100                 c.Accelerate(20);
    101                 //注销第二个处理程序
    102                 c.UnRegisterWithCarEngine(handler);
    103                 //Console.ReadLine();
    104             }
    105             Console.WriteLine("**** Delegate Convariance ****");
    106             ObtainVehicleDelegate targetA = new ObtainVehicleDelegate(GetbasicCar);
    107             Car car = targetA();
    108             Console.WriteLine("Obtiond a {0}",car);
    109 
    110             ObtainVehicleDelegate targetB = new ObtainVehicleDelegate(GetSportCar);
    111             SportCar sportCar = (SportCar)targetB();
    112             Console.WriteLine("Obtiond a {0}", sportCar);
    113             Console.ReadKey();
    114 
    115         }
    116         public static void OnCarEngineEvent(string msg)
    117         {
    118             Console.WriteLine("\n****Message From Car Object****");
    119             Console.WriteLine("==》{0}", msg);
    120             Console.WriteLine("*********************************\n");
    121         }
    122         public static void OnCarEngineEvent2(string msg)
    123         {
    124             Console.WriteLine("==》:{0}", msg.ToUpper());
    125         }
    126 
    127             #endregion
    128         #region 委托协变
    129 
    130         public delegate Car ObtainVehicleDelegate();
    131 
    132         public static Car GetbasicCar()
    133         {
    134             return new Car();
    135         }
    136 
    137         public static SportCar GetSportCar()
    138         {
    139             return new SportCar();
    140         }
    141 
    142         #endregion
    143     
    144     }
    145 }

      

    运行结果如下:

    下面再学习下 Generic Delegate吧

    例如我们想定义一个委托类型来调用任何返回void并且接受单个参数的方法。如果这个参数可能会不同;我们就可以使用类型参数来构建简单的例子来帮助理解:

    代码:

    View Code
     1 View Code 
     2 
     3 using System;
     4 using System.Collections.Generic;
     5 using System.Linq;
     6 using System.Text;
     7 
     8 namespace Generic_Delegate
     9 {
    10    public class Program
    11     {
    12        public delegate void MyGenericDelegate<T>(T arg);
    13         static void Main(string[] args)
    14         {
    15             Console.WriteLine("***** Generic Delegate *****");
    16 
    17             //注册目标
    18             MyGenericDelegate<string> strTarget = new MyGenericDelegate<string>(StringTaget);
    19             strTarget("some String Data");
    20             MyGenericDelegate<int> intTarget = new MyGenericDelegate<int>(IntTarget);
    21             intTarget(9);
    22             Console.ReadLine();
    23         }
    24         static void StringTaget(string arg)
    25         {
    26             Console.WriteLine("arg in uppercase is :{0}",arg.ToUpper());
    27         }
    28         static void IntTarget(int arg)
    29         {
    30             Console.WriteLine("++arg is {0}",++arg);
    31         }
    32     }
    33 }

    到这委托的学习就差不多了。

  • 相关阅读:
    JS处理日期&字符串格式相互转换
    Ajax 原理过程 同步与异步区别 优缺点
    元素居中
    width:100%;与width:auto;的区别
    URL、URI和URN三者之间的区别
    JavaScript encodeURI(), decodeURI(), encodeURIComponent(), decodeURIComponent()
    CSS 笔记三(Tables/Box Model/Outline)
    CSS 笔记二(Text/Fonts/Links/Lists)
    CSS 笔记一(Selectors/ Backgrounds/ Borders/ Margins/ Padding/ Height and Width)
    javascript,jQuery,trim()
  • 原文地址:https://www.cnblogs.com/lvfeilong/p/FDFDFDF.html
Copyright © 2011-2022 走看看