委托

委托的定义

  • 委托是一个自定义数据类型。所以通常定义在namespace里。
  • 委托代表一个函数的定义,用于说明函数长什么样,输入参数是什么、返回值是什么类型,但没有函数体。
    delegate double Compute(double number1, double number2);
    

委托的作用

  • 委托可以用来定义函数变量。

委托的使用

  • 委托既然是一种数据类型那就可以用来申明变量。
  • 委托数据类型的变量要赋值为一个函数。
  • 赋值给委托变量的函数一定要和委托定义的函数原型一样,即输入参数和返回值一样。
  • 赋值给委托变量的函数是一个有函数体的具体函数。好吧,这是句废话。
  • 调用委托就是调用其对应的函数。
    public double Add(double a, double b)
    {
      return a + b;
    }
    public void Test()
    {
      Compute c = Add; // 委托变量可以用来存一个具体的函数
      Console.WriteLine(Add(1, 2)); // 输出:3。
      Console.WriteLine(c(1, 2)); // 输出:3。变量可以用来替代其存储的数据,所以Add可以用c替代。
    }
    
    public double Add(double a, double b)
    {
      return a + b;
    }
    public double Sub(double a, double b)
    {
      return a - b;
    }
    public void Fun()
    {
    }
    public void Test()
    {
      // 申明委托变量
      Compute c = Add;
      Console.WriteLine(c(1, 2)); // OK: 输出:3。
      // 修改委托变量
      // c = Fun; // ERROR: Fun函数的定义与Compute委托的定义不一致。
      c = Sub; // OK: c是变量所以可以重新赋值。
      Console.WriteLine(c(1, 2)); // 输出:-1。
    }
    

委托的应用场景

上例中不是可以直接调用Add吗,为什么要用委托变量间接的调用呢?是的,这样做确实意义不大,完全可以不使用委托来实现。

  • 委托变量通常不是在当前类中由自己来赋值的。而是由外部使用者来赋值。当前类中不知道调用哪个函数时才使用委托。
  • 委托的使用场景主要有两种:事件和回调。
  • 委托用于事件。事件是指当某个事情发生时去做什么,这种情况下要调用的函数无法事先预知,所以使用委托。

    // 定义死亡委托
    delegate void DeadHandler();
    // 定义死亡事件
    public DeadHandler Dead {get; set;}
    // 当被攻击时调用
    void OnAttacked()
    {
      if (HP <= 0)
      {
          // 血量低于0就死亡了
          if (Dead != null)
              Dead(); // 用户给Dead赋值为哪个函数,这里就会调用哪个函数。但当前类中并没有给Dead赋值,而是由交由使用者去赋值。
      }
    }
    
  • 委托用于回调。将委托作为函数参数来实现回调。(新手可以先忽略)

    // complete: 下载完成的百分比;data:本次下载的数据。
    delegate void DownloadHandler(double complete, byte[] data);
    // 下载函数。每当下载完一个缓存的数据,就会回调handler所指定的函数。
    void Download(DownloadHandler handler)
    {
      if (handler!=null) 
          handler();
    }
    

委托传参(新手可以先忽略,后续补充)

常见错误

  • 委托变量可以调用,委托类型是不能调用的。

    // 定义死亡委托
    delegate void DeadHandler();
    // 当被攻击时调用
    void Test()
    { 
      // DeadHandler(); // ERROR:数据类型是不能直接调用的
      DeadHandler dead = Fun;
      dead(); // OK: 调用dead变量,相当于调用了对应的Fun函数。
    }
    void Fun()
    {
    }
    
  • 给委托变量赋值时,函数名后加不加()。

    // 定义死亡委托
    delegate void DeadHandler();
    // 当被攻击时调用
    void Test()
    { 
      DeadHandler dead;
      dead = Fun1; // OK: Fun1代表一个函数(的内存地址)
      // dead = Fun1(); // ERROR: Fun()是函数的调用,这里相当于使用了Fun()的返回值。
      dead = Fun2(); // OK: Fun2()的返回值是DeadHandler类型与dead的类型一致。
    }
    void Fun1()
    {
    }
    DeadHandler Fun2()
    {
      return Fun1;
    }
    

results matching ""

    No results matching ""