理解C#委托(Delegate)通俗易懂,深入浅出

委托是什么?

委托首先是一个数据类型,我们可以像定义结构体一样定义一个委托类型,委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变

委托的定义

//语法
delegate <return type> <delegate-name> <parameter list>
//实例
public delegate int MyDelegate (string s);

实例化委托(Delegate)

例如:

public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);

说白了就是类似指向函数方法的指针,我们可以类似定义指针类型一样,定义委托的类型

在定义委托类型时要指定函数的参数类型和返回值,一旦声明了委托类型,委托对象必须使用 new 关键字来创建,且与一个特定的方法有关。当创建委托时,传递到 new 语句的参数就像方法调用一样书写,但是不带有参数。

简单用法实例

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
    
    
   class TestDelegate
   {
    
    
      static int num = 10;
      public static int AddNum(int p)
      {
    
    
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
    
    
         num *= q;
         return num;
      }
      public static int getNum()
      {
    
    
         return num;
      }

      static void Main(string[] args)
      {
    
    
         // 创建委托实例
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         // 使用委托对象调用方法
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

这只是简单的用法介绍,可以看出 这和在主程序里直接调用方法没啥区别,并不是实际的用法。

委托的用途

多播

委托对象可使用 “+” 运算符进行合并。一个合并委托调用它所合并的两个委托。只有相同类型的委托可被合并。"-" 运算符可用于从合并的委托中移除组件委托。

使用委托的这个有用的特点,您可以创建一个委托被调用时要调用的方法的调用列表。这被称为委托的 多播(multicasting),也叫组播。下面的程序演示了委托的多播

static void Main(string[] args)
      {
    
    
         // 创建委托实例
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         nc = nc1;
         nc += nc2;
         // 调用多播
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

关键: 委托的使用场景

委托,故名思意,咱们用一个形象的比喻,公司里 ,老板/调用者 ,可以不用委托我/激活委托函数,亲自去给张三/func1,李四/func2 安排工作,就是直接调用,这时或许要准备调用的参数和调用方式的代码 比如循环调用,
老板/调用者 还可以通过我/激活委托的函数 去安排张三李四的工作,同时也可以指定张三/func1,李四/func2 一起工作/±多播,也可以拓展新的员工/方法。
和类的继承多态有异曲同工之妙,不过更加灵活,我/激活委托函数 不需要知道自己要调用什么函数以及具体实现,只管用调用者给的参数就行了 ,父类不用管子类如何实现的,通过子类型的赋值,就能调用子类重写的方法。


        //委托

        // 委托声明
        public delegate void doSomething(string s);
		//定义 回调函数  ,公司里的员工 张三,李四.............
		public static void ZangSan(string a) {
    
    
			Console.WriteLine("zhangsan"+a);
		}
        public static void LiSi(string a)
        {
    
    
            Console.WriteLine("lisi"+a);
        }
        /// <summary>
        /// 中介,委托处理 ,使用此方法触发委托回调
        /// </summary>
        /// <param name="from">开始</param>
        /// <param name="to">结束</param>
        /// <param name="fb">委托引用</param>      
            private static void handleDelegate(int from, int to, doSomething ds)
            {
    
    
			//一些预处理 ,这样使用委托就比直接调用方便了
                for (int val = from; val <= to; val++)
                {
    
    
                 
                    if (ds != null)
                    {
    
    
                        ds(val.ToString());
                    }
                    //ds?.Invoke(val); 简化版本调用
                }
            }
        

        //主函数,调用者 老板
        public void testDelegate()
        {
    
         //老板通过我/中介 给张三安排工作,
			doSomething dsZhangSan = new doSomething(ZangSan);
			//给张三李四 按顺序安排工作  //按序执行
			doSomething dsLisi = new doSomething(LiSi);
			doSomething ds = dsZhangSan + dsLisi;
			//在调用的时可以给张三,李四传参数,这里在handleDelegate里面给了 ds(val.ToString());
			handleDelegate(0, 3, ds);

			//方法的返回值,参数必须完全一样,符合委托类型的定义
		}

执行结构

在这里插入图片描述

回调函数的机制

把我想象成是独立的提供服务的中介,而老板/函数实现的一方, 张三/func1,李四/func2 ~~~是一个公司的,合作时,老板指定张三或是李四… , 而我不需要关心,我只是在特点条件发生时去调用张三李四就行了

⑴定义一个回调函数;
⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。

猜你喜欢

转载自blog.csdn.net/qq_43886548/article/details/127882628