什么是委托?

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

委托是一种动态调用方法的类型,属于引用型。

委托是对方法的抽象和封装。委托对象实质上代表了方法的引用(即内存地址)

可以理解为函数的一个包装,它使得c#中的函数可以作为参数来被传递

简单理解是这样的

比如您要管您的孩子,把孩子送进了幼儿园

OK,此时您就把您的孩子委托给了幼儿园

当幼儿园放学,将孩子交还给您的手中则是委托的回调

当然我这里的例子是说异步委托调用,您也可以同步

什么是同步委托调用?

您去银行存钱,把钱给柜员,他们帮你点钞,存款然后给您存折或卡

那么您就相当于把钱委托给了柜员让他去执行存钱的这个函数

委托的定义

1. 以delegate关键字开头。

2. 返回类型+委托类型名+参数列表

public delegate void MyDelegate(int para1, string para2);

委托能包装的方法是有一定限制的,例如能被前面的委托类型MyDelegate包装的方法需要满足以下条件:

    1.方法的返回类型必须为void;

    2.方法必须有两个参数,并且第一个参数应为int类型,第二个参数为string类型。

总结:可以被委托包装的方法必须满足以下规则:

    1.方法的签名必须与委托一致,方法签名包括参数的个数、类型和顺序;

    2.方法的返回类型要和委托一致,注意,方法的返回类型不属于方法签名的一部分。

 委托的使用

//委托使用的演示
    class Program
    {
        //1.使用delegate关键字来定义一个委托类型
        public delegate void MyDelegate(int para1, int para2);
        static void Main(string[] args)
        {
            //2.声明委托变量d
            MyDelegate d;

            //3.实例化委托类型,传递的方法也可以为静态方法,这里传递的是实例方法
            d = new MyDelegate(new Program().Add);

            //4.委托类型作为参数传递给另一个方法
            MyMethod(d);

            Console.ReadKey();
        }

        void Add(int para1,int para2)
        {
            int sum = para1 + para2;

            Console.WriteLine("两个数的和为:" + sum);
        }

        private static void MyMethod(MyDelegate mydelegate)
        {
            //5.在方法中调用委托
            mydelegate(1, 2);
        }
    }

 从以上代码可以看出,使用委托的步骤为:定义委托类型—声明委托变量—实例化委托—作为参数传递给方法—调用委托。如下具体分析委托的使用过程。

  (1)定义委托类型:public delegate void MyDelegate(int para1, int para2) 其定义方式类似于方法的定义,只是多了一个delegate关键字。

  (2)声明委托变量:MyDelegate d;既然委托是一种类型,那么可以使用委托来声明一个委托变量,相当于int a;

  (3)实例化委托: d = new MyDelegate(new Program().Add);。第二步只是声明了委托变量,但并没有将它实例化。类的实例化使用new关键字来实现,而委托也属于类类型,所以委托的实例化也使用new关键字来进行的。这里需要注意的是,委托的实例化是用一个方法名(不能带左右括号)作为参数,并且该方法的定义必须符合委托的定义,即该方法的返回类型、参数个数和类型必须与委托定义中的一样。这样,前面3步就好比构造了一个律师对象,而方法InstanceMethod好比是当事人的方法。

  (4)作为参数传递给方法:MyMethod(d);。委托使用得在C#中,可以把一个方法作为另一个方法的参数,而委托可以看作是一个包装方法的对象。

  (5)在方法中调用委托。MyMethod(d);。委托使用得在c#中,可以把一个方法作为另一个方法的参数,而委托可以看作是一个包装方法的对象。

   总结:在使用委托时,需要注意以下几个问题。

    1.在第三步中,被传递的方法的定义必须与委托定义相同,即方法的返回类型和参数个数、参数类型都必须与委托相同。并且,传递的是方法名,方法名后不能带有左右括号。

    2.在第五步中,委托的调用与方法调用类似,传递的实参类型和个数必须与委托定义一致。

    3.由于委托是方法的包装类型,所以对委托的调用也就是对其所包装的的方法的调用,上面第5步时间上是调用了Add方法来对传入的实参进行计算。

为什么要使用委托

委托使得一个方法可以作为另一个方法的参数进行传递,这就是委托最大的作用。使用委托可以将同类型的方法绑定到同一个变量上,当调用此变量时就可以一次调用绑定的方法,很方便。如下例子:

例如我们要实现一个打招呼的方法,而每个国家打招呼的方式都不一样,刚开始我们可能会像下面这样实现打招呼的方法:

public void Greeting(string name,string language)
        {
            switch (language)
            {
                case "zh-cn":
                    ChineseGreeting(name);
                    break;
                case "en-us":
                    EnglishGreeting(name);
                    break;
                default:
                    EnglishGreeting(name);
                    break;
            }
        }

        public void EnglishGreeting(string name )
        {
            Console.WriteLine("Hello, " + name);
        }

        public void ChineseGreeting(string name)
        {
            Console.WriteLine("你好, " + name);
        }

若后续我们需要添加德国、日本等打招呼方法,就必须修改Greeting方法内的case语句,来适应新的需求,这样特别不方便。有了委托,我们就可以把函数作为参数,并像如下代码实现Greeting方法:

public delegate void GreetingDelegate(string name);

        static void Main(string[] args)
        {
            //引入委托
            Program p = new Program();

            p.Greeting("小叶", p.ChineseGreeting);

            p.Greeting("Tommy Li", p.EnglishGreeting);

            Console.Read();

        }

        public void Greeting(string name,GreetingDelegate callback)
        {
            callback(name);
        }
        public void EnglishGreeting(string name)
        {
            Console.WriteLine("Hello, " + name);
        }

        public void ChineseGreeting(string name)
        {
            Console.WriteLine("你好, " + name);
        }

如下,增加德国人打招呼:

class Program
    {
        public delegate void GreetingDelegate(string name);

        static void Main(string[] args)
        {
            //引入委托
            Program p = new Program();

            p.Greeting("小叶", p.ChineseGreeting);

            p.Greeting("Tommy Li", p.EnglishGreeting);

            p.Greeting("Ha Wa", p.GermanyGreeting);

            Console.Read();

        }

        public void Greeting(string name,GreetingDelegate callback)
        {
            callback(name);
        }
        public void EnglishGreeting(string name)
        {
            Console.WriteLine("Hello, " + name);
        }

        public void ChineseGreeting(string name)
        {
            Console.WriteLine("你好, " + name);
        }

        public void GermanyGreeting(string name)
        {
            Console.WriteLine("Hallo, " + name);
        }
    }

委托链的使用

委托链其实就是委托类型,只是委托链把多个委托链接在一起而已,也就是说,我们把链接了多个方法的委托称为委托链或多路广播委托。如下:

public delegate void DelegateTest();



        static void Main(string[] args)
        {
            //用静态方法来实例化委托
            DelegateTest dtstatic = new DelegateTest(Program.method1);

            DelegateTest dtinstance = new DelegateTest(new Program().method2);

            //定义一个委托对象,一开始初始化为null,即不代表任何方法。
            DelegateTest delegatechain = null;

            //使用 “+”符号链接委托,链接多个委托后就成为了委托链

            delegatechain += dtstatic;
            delegatechain += dtinstance;

            //调用委托链
            delegatechain();
            Console.Read();

        }
        private static void method1()
        {
            Console.WriteLine("这是静态方法");
        }

        //实例方法

        private void method2()
        {
            Console.WriteLine("这是实例方法");
        }

从委托链中移除委托

public delegate void DelegateTest();


        static void Main(string[] args)
        {
            //用静态方法来实例化委托
            DelegateTest dtstatic = new DelegateTest(Program.method1);

            DelegateTest dtinstance = new DelegateTest(new Program().method2);

            //定义一个委托对象,一开始初始化为null,即不代表任何方法。
            DelegateTest delegatechain = null;

            //使用 “+”符号链接委托,链接多个委托后就成为了委托链

            delegatechain += dtstatic;
            delegatechain += dtinstance;

            //使用 “-”运算符 移除委托 
            delegatechain -= dtstatic;
            //调用委托链
            delegatechain();
            Console.Read();

        }
        private static void method1()
        {
            Console.WriteLine("这是静态方法");
        }

        //实例方法

        private void method2()
        {
            Console.WriteLine("这是实例方法");
        }
使用委托可以将多个方法绑定到同一个委托变量,当调用此变量时(这里用“调用”这个词,是因为此变量代表一个方法),可以依次调用所有绑定的方法。

 

 

 

 

参考链接:https://www.cnblogs.com/xiaoyehack/tag/c%23%20%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/default.html?page=1

 

 

 

 

 

 

02-10 19:02