什么是委托,非自定义委托与自定义委托

C语言中的函数指针:


一切皆地址:
程序的本质是变量+算法
变量是以变量名对应内存地址为起点的一段内存,其所存储的数据就是变量里的数据,这段内存的大小由变量的数据类型决定->变量是地址。
函数是以函数名对应的内存地址为起点的一段内存,这段内存存储的不是某个值,而是一组机器语言的指令,CPU按照这组指令一条条执行,完成我们函数中所包含的算法->函数是地址。

直接调用与间接调用的本质:
直接调用:
CPU通过函数名找到这段地址,然后执行指令,执行完最后一条,CPU返回到调用者那里去。
间接调用:
CPU通过某个指向某函数的函数指针来间接调用函数,函数指针是一个变量,它存储函数名所对应的那个地址,找到地址后,后面是一样的。

C#通过委托来保留C语言中的间接调用功能,Java则完全舍弃了这部分功能,禁止直接访问内存。

委托就是函数指针的升级。

C语言中需要先声明函数指针类型,才能使用这个类型。
而C#类库中已经为我们准备好了很多可以直接使用的委托类型。
常用的有Action(无返回值的方法专用),Function等
举个例子,我们建一个计算器类:

    class Calculator
    {
        public void Report()
        {
            Console.WriteLine("I have 3 methods.");
        }
        public int Add(int a, int b)
        {
            int result = a + b;
            return result;
        }

        public int Sub(int a, int b)
        {
            int result = a - b;
            return result;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();
            Action action = new Action(calculator.Report);
            calculator.Report();//直接调用
            action.Invoke();//间接调用(使用action委托)
            action(); //间接调用的简洁版
        }
    }

代码分析,Calculator是计算器类,我们建立它的实例calculator然后,
建立Action实例action,它的构造函数要求我们输入一个:
参数列表为空,无返回值(返回值为void)的方法。

Report方法满足这个条件。
所以:
Action委托是专门应对——无返回值(返回值为void)的方法的。

对于有返回类型和有参数的方法,我们使用Func委托:


Func<>委托有若干的重载,前面的是参数类型,最后一项是返回值类型。

在这里我们用第二种。

要求我们在Func的构造函数里填写匹配的方法,我们写入Add和Sub方法。

    class Program
    {
        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();
            Func<int, int, int> func1 = new Func<int, int, int>(calculator.Add);
            Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);
            int z = 0;
            z = func1.Invoke(100, 200);//间接调用(使用Func委托),还可以简写为z = func1(200,100);
            Console.WriteLine(z);
            z = func2.Invoke(100, 200);//间接调用(使用Func委托)
            Console.WriteLine(z);
        }
    }

委托是个类,我们来验证一下

using System;
using System.Collections.Generic;

namespace CustomizeDelegate

{

  class Program
  {
    static void Main(string[] args)  
    {
      Type t = typeof(Action);
      Console.WriteLine(t.IsClass);//返回true,说明Action委托是类

    }

  }

}

程序结果:
true
所以证明委托是个类。

自定义一个委托:

参数类型,返回类型必须一一对应(名称可以不同)

委托类,因为是类,与其他类平级,所以声明在命名空间里,他的声明格式是仿照函数指针。

    public delegate double Calc{double x, double y};

定义一个计算机类Calculator

    class Calculator
    {
        public double Add(double x, double y)
        {
            return x + y;
        }
        public double Sub(double x, double y)
        {
            return x - y;
        }
        public double Mul(double x, double y)
        {
            return x * y;
        }
        public double Div(double x, double y)
        {
            return x / y;
        }
    }

创建Calculator类实例calculator ,然后创建Calc委托的实例calcAdd等等。

    class Program
    {
        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();

            Calc calcAdd = new Calc(calculator .Add);
            Calc calcSub = new Calc(calculator .Sub);
            Calc calcMul = new Calc(calculator .Mul);
            Calc calcDiv = new Calc(calculator .Div);

            double result = 0;

            result  = calcAdd.Invoke(100, 200);//间接调用(使用Calc委托)
            Console.WriteLine(result);
            result  = calcSub(100, 200);//间接调用(使用Calc委托)
            Console.WriteLine(result);
            result  = calcMul(100, 200);//间接调用(使用Calc委托)
            Console.WriteLine(result);
            result  = calcDiv(100, 200);//间接调用(使用Calc委托)
            Console.WriteLine(result);
        }
    }

结果是:

原文地址:https://www.cnblogs.com/maomaodesu/p/11393254.html