委托

        委托是C#1.0提出的一种功能,如今C#都将更新到C#10.0了(最新8.0),对委托的用法还只是停留在原地,略等于不知道。今天自己来学习,解锁下“委托”这个技能,本文综合圈子各位大佬的文章总结而来,若有错误或不足,欢迎斧正。

        委托在.net framwork中的应用非常广泛(CS项目中经常用到,BS项目相对要少点);本文将讲述委托的概念(什么是委托 What)、委托的作用(为什么要使用委托 Why)、委托怎么用(How);

委托的概念-WHAT:

       委托:把事情托付给别人或别的机构(办理)(百度百科释义:https://baike.baidu.com/item/%E5%A7%94%E6%89%98/34711?fr=aladdin);直观点就是,本该自己做的事情,交给别人做;

       C#中的委托:委托实际为一种 中间人 ,A需要C去做某件事情 而由B去调用C来做事。委托是用户自定义的类,它定义了方法的类型。储存的是一系列具有相同参数和返回类型方法的地址列表,调用委托时,此委托列表的所有方法都将被执行。总的来说:委托是方法的抽象,它代表了一组方法的共同特征。

委托的作用-WHY:

      用来实现传递回调函数;将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。

委托的用法-HOW:

     1:先声明定义一个委托

     2:实例化一个委托,实例化的时候需要绑定方法(绑定的方法必须与定义的委托具有相同参数列表和返回值,否则编辑器会报错)

     3:调用委托    

  • 定义委托的关键词:delegate
  • 委托是一种类型,它可以声明在类的外部,也可以在类的内部声明;
using System;
using System.Collections.Generic;
using System.Text;

namespace Tools
{
    public delegate void MyDelegateOutClass();//类外部申请一个委托
    public class LearnDelegate
    {
        public delegate void MyDelegateInClass();//类内部申请一个委托
    }
}
  • 示例一:无参数、无返回值委托和方法绑定
    public class LearnDelegate
    {
        //1:声明一个无参数无返回值的委托
        public delegate void MyDelegateNoParmNoreturn();public static void Run()
        {
            //1:无参数无返回值的委托实例化与调用
            MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns);
            method1.Invoke();
        }
        public static void NoParmsNoReturns()
        {
            Console.WriteLine("这是一个无参数、无返回值的方法");
        }
    }

  从示例一可以看出:委托的实例化和类的实例化相似:在使用委托的时候,你可以像对待一个类一样对待它。即1:先声明:2:再实例化。只是有点不同,类在实例化之后叫对象或实例,但委托在实例化后仍叫委托;委托的实例化需要绑定方法,也就是委托要办的事情

  • 示例二:有参数无返回值委托和方法绑定
    public class LearnDelegate
    {
        //1:声明一个无参数无返回值的委托
        public delegate void MyDelegateNoParmNoreturn();

        //2:声明一个有参数无返回值的委托
        public delegate void MyDelegateHasParmsNoReturn(string name, string sex);
public static void Run()
        {
            //1:无参数无返回值的委托实例化与调用
            MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns);
            method1.Invoke();

            //2:有参数无返回值的委托实例化与调用
            MyDelegateHasParmsNoReturn method2 = new MyDelegateHasParmsNoReturn(HasParmsNoReturns);
            method2("zhangsan", "");
        }
        public static void NoParmsNoReturns()
        {
            Console.WriteLine("这是一个无参数、无返回值的方法");
        }

        public static void HasParmsNoReturns(string _name)
        {
            Console.WriteLine("这是一个有参数、无返回值的方法");
        }
    }
  • 示例三:有参数、有返回值的委托和方法绑定
public class LearnDelegate
    {
        //1:声明一个无参数无返回值的委托
        public delegate void MyDelegateNoParmNoreturn();

        //2:声明一个有参数无返回值的委托
        public delegate void MyDelegateHasParmsNoReturn(string name, string sex);

        //3声明一个有参数有返回值的委托
        public delegate string MyDelegateHasParmsHasReturn(string name);
        public static void Run()
        {
            //1:无参数无返回值的委托实例化与调用
            MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns);
            method1.Invoke();

            //2:有参数无返回值的委托实例化与调用
            MyDelegateHasParmsNoReturn method2 = new MyDelegateHasParmsNoReturn(HasParmsNoReturns);
            method2("zhangsan", "");

            //3:有参数有返回值的委托实例化与调用
            MyDelegateHasParmsHasReturn method3 = new MyDelegateHasParmsHasReturn(HasParmsHasReturns);
            var name = method3("lisi");
        }
        public static void NoParmsNoReturns()
        {
            Console.WriteLine("这是一个无参数、无返回值的方法");
        }

        public static void HasParmsNoReturns(string _name)
        {
            Console.WriteLine("这是一个有参数、无返回值的方法");
        }
        public static string HasParmsHasReturns(string _name)
        {
            Console.WriteLine("这是一个有参数、有返回值的方法");
            return "";
        }

        public static void HasParmsNoReturns(string _name, string _sex)
        {
            Console.WriteLine("这是一个有两个参数、无返回值的方法");
        }


    }
  • 自带委托Action
    • Action为C#自带的委托类型,无需另外声明委托,可直接创建一个委托实例
    • Action为无返回值的委托类型
 public static void HasParmsNoReturns(string _name, string _sex)
        {
            Console.WriteLine("这是一个有两个参数、无返回值的方法");
        }

        public static void ShowAction()
        {
            Action action = new Action(NoParmsNoReturns);
            action(); //委托实例调用 => action.Invoke();

            Action<string,string> action2 = new Action<string,string>(HasParmsNoReturns);
            action2("","");//有参数 无返回值,此时参数类型必须标明在声明委托中
        }
  • 自带委托 Func
    • Func 为C#自带的委托类型,无需另外声明委托,可直接创建一个委托实例
    • Func 为有返回值的委托类型
 public static string HasParmHasReturn(string name,string address,string email)
        {
            return "hello world";
        }

        public static void ShowFunc()
        {
            Func<string> fun1 = new Func<string>(NoParmHasReturn);
            fun1();//无参数,有返回值


            Func<string, string, string,string> fun2 = new Func<string, string, string,string>(HasParmHasReturn);
            fun2("","",""); //有参数,有返回值
        }

注意:当Func中只有一个参数,说明需要绑定的是无参数的有返回值的方法,Func的唯一参数为返回值类型;

          Func中的参数类型、返回值类型都需要标明,在泛型类声明中,当有返回值得时候,最后一个参数类型为返回值类型

参数我们试下将方法的返回值类型改为int,编译报错;

 正确写法:

        public static int HasParmHasReturn(string name,string address,string email)
        {
            return 123;
        }

        public static void ShowFunc()
        {
            Func<string> fun1 = new Func<string>(NoParmHasReturn);
            fun1();


            Func<string, string, string,int> fun2 = new Func<string, string, string,int>(HasParmHasReturn);
            fun2("","",""); 
        }
  • 多播委托
    • 只需要调用一个委托,就可以一次执行这个委托中包含的所有方法(一个委托能够指向多个函数方法)
    • 多播委托引用的函数的返回类型必须是void,否则,我们只能得到最后一个函数调用结果。

使用示例:

        /// <summary>
        /// 多播委托使用示例
        /// </summary>
        public static void ShowMore()
        {
            Action action = Show1;
            action += Show2;
            action += Show3;
            action += Show4;
            action -= Show3;
            action += Show3;

            action();

            Console.ReadLine();
        }
        public static void Show1()
        {
            Console.WriteLine("show T1");
        }
        public static void Show2()
        {
            Console.WriteLine("show T2");
        }
        public static void Show3()
        {
            Console.WriteLine("show T3");
        }
        public static void Show4()
        {
            Console.WriteLine("show T4");
        }

看到示例,可能会有点懵;我们先看下运行结果,在作分析:

 

 

 其中有

  1. 委托名=方法名 :实例化委托赋值语法的简写
  2. “+=方法名”  :委托绑定方法,将相同参数列表的函数绑定到统一委托中执行
  3. “-=方法名”  :取消委托绑定的方法,将方法从委托方法列表中移除

这个是委托实例化的简写  即

MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns);
 //等效于
MyDelegateNoParmNoreturn method1 = NoParmsNoReturns;

注:第一次用的“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。

然后我们来看多播委托的执行过程:

首先我们用了C#自带的无返回值的Action,赋值了一个Show1的方法;然后为该委托绑定了Show2、Show3、Show4的方法;再然后取消了Show3的绑定,最后又重新绑定了Show3;所以该委托依次执行结果为:show T1 、show T2、show T3(后被移除不输出)、showT4、showT3(重新绑定ShowT3,最后输出)

总结:使用委托可以将多个方法绑定到同一个委托变量,当调用此委托,可以依次调用所有绑定的方法

 

posted @ 2021-09-16 17:12  #疆先绅#  阅读(88)  评论(0编辑  收藏  举报