C#深入浅出 C#语法中的重中之重——委托(四)

  入行半年多了,委托干什么用的还不知道,真心说不过去了,关键对这东西有点恐惧,主要是被老师吓的,记得我C#专业课老师在讲到委托时,原话是这样的,同学们,委托这个地方是难点,暂时不讲,讲了你也不懂,等你有了一定的编程经验,你自会明白。好吧,我懂了,只可意会不可言传。其实,它并没有想象中这么恐怖,只不过我被吓着了,向来就胆小,不敢挑战有点难度的东西,只能玩玩表面的东西,嗨,不废话了,但是这是按照博客园惯例来的,一开始不能太专业,专业了就不是“面向对象”了。

  好吧,先提个问题,委托到底是什么?这是个头脑风暴,那家可以随便想.......是类型?是方法?还是是对象?   大家有没有说说你的见解的,大多数教程里更愿意把它叫做代理,叫做方法的指针,好吧,又专业了。其实我认为,这几种的叫法都合适。那它到底是什么?有什么用?为了让不懂编程的人也能看懂我写的东西,我举个实际生活中的例子,比如,二狗,我今天有点事,孩子放学回家没人做饭,我今天就把他暂时交给你照顾了,好吗?那这里做饭这件事其实就是C#中的方法,一个事件的处理过程,二狗就是你的委托人,本来你是孩子的监护人,你理应直接照顾孩子的吃饭上学等等,但是今天特殊情况,自己实在做不了,你就把这事暂时委托给你的朋友,让他帮一下吗。相信大家懂了吗,有没有稍微懂,稍微懂就够了,我们可以跳到C#里来,重新讲述一下委托这个概念,C#中,你本可以直接操作方法,你是方法的创造者(自定义方法),或者,C#为你做好的方法(类库里的方法),但是我把方法委托给别人来做,但是这个人要有和我一样的能耐(可以为理解方法签名要一致)才能帮我完成方法的调用。

  补充方法签名的概念,方法签名指方法名称、参数个数、参数类型、方法参数的顺序。与方法返回值无关。方法签名也成为方法标识。

  TIP:"在方法重载的上下文中,方法的签名不包括返回值。 但在委托的上下文中,签名包括返回值。 换句话说,方法和委托必须具有相同的返回类型。"来自MSDN

  接下来我们按照委托如何定义,如何使用,为什么要使用委托几个角度学习它。并与C语言中函数指针类比学习。

  以实现四则计算器为目的,首先定义加、减、乘、除四个计算方法,在主函数中使用委托的方式进行调用。

class Program

    {

        delegate int MathDelegate(int i, int j);//delegate 和 Delegate 的区别是什么

        static int Add(int i,int j)

        {

            return i+j;

        }

        static int Subtract(int i,int j)

        {

            return i - j;

        }

        static int multiply(int i,int j)

        {

            return i * j;

        }

        static int devide(int i,int j)

        {

            return i / j;

        }

        static void Main(string[] args)

        {

            MathDelegate myDelegate = new MathDelegate(Add);

            int result=myDelegate(10,20);

            Console.WriteLine("加法结果是:{0}",result);



            myDelegate = new MathDelegate(Subtract);

            result = myDelegate(10, 20);

            Console.WriteLine("减法结果是:{0}", result);



            myDelegate = new MathDelegate(multiply);

            result = myDelegate(10, 20);

            Console.WriteLine("乘法结果是:{0}", result);



            myDelegate = new MathDelegate(devide);

            result = myDelegate(10, 20);

            Console.WriteLine("除法结果是:{0}", result);



            Console.ReadKey();

        }

    }

 

如同i可以接受int类型的“1”,但不能接受bool类型的1一样。MathDelegata的 参数类型定义 应该能够确定 MathDelegata可以代表的方法种类,再进一步讲,就是MathDelegata可以代表的方法 的 参数类型和返回类型,就是方法签名的意思。

于是,委托出现了:它定义了MathDelegata参数所能代表的方法的种类,也就是MathDelegata参数的类型。

NOTE:如果上面这句话比较绕口,我把它翻译成这样:string 定义了name参数所能代表的值的种类,也就是name参数的类型。

        static int Count(int i, int j, MathDelegate myDelegata)

        {

            return myDelegata(i,j);

        } 

如你所见,委托MathDelegata出现的位置与 int相同,int是一个类型,那么MathDelegata应该也是一个类型,或者叫类(Class)。但是委托的声明方式和类却完全不同,这是怎么一回事?实际上,委托在编译的时候确实会编译成类。因为Delegate是一个类,所以在任何可以声明类的地方都可以声明委托。更多的内容将在下面讲述,现在,请看看这个范例的完整代码:

class Program

    {

        delegate int MathDelegate(int i, int j);//delegate 和 Delegate 的区别是什么

        static int Add(int i,int j)

        {

            return i+j;

        }

        static int Subtract(int i,int j)

        {

            return i - j;

        }

        static int Multiply(int i,int j)

        {

            return i * j;

        }

        static int Devide(int i,int j)

        {

            return i / j;

        }

        static int Count(int i, int j, MathDelegate myDelegata)

        {

            return myDelegata(i,j);

        }

        static void Main(string[] args)

        {

            int result = Count(20, 10, Add);

            Console.WriteLine("加法结果是:{0}",result);



            result = Count(10, 20,Subtract);

            Console.WriteLine("减法结果是:{0}", result);



            result = Count(10, 20,Multiply);

            Console.WriteLine("乘法结果是:{0}", result);



            result = Count(10, 20, Devide);

            Console.WriteLine("除法结果是:{0}", result);



            Console.ReadKey();

        }

我们现在对委托做一个总结:

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

说到这里我们已然可以把委托理解为一个类型或一个类,就想String一样,但是委托有一个特性不同于类型:可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。我们称它为多播委托,在这个例子中,语法如下:

 

 class Program

    {

        delegate int MathDelegate(int i, int j);//delegate 和 Delegate 的区别是什么

        static int Add(int i,int j)

        {

            Console.WriteLine("加法");

            return i+j;

        }

        static int Subtract(int i,int j)

        {

            Console.WriteLine("减法");

            return i - j;

        }

        static int Multiply(int i,int j)

        {

            Console.WriteLine("乘法");

            return i * j;

        }

        static int Devide(int i,int j)

        {

            Console.WriteLine("除法");

            return i / j;

        }

        static int Count(int i, int j, MathDelegate myDelegata)

        {

            return myDelegata(i,j);

        }

        static void Main(string[] args)

        {          

            //多播委托

            MathDelegate myDelegate = new MathDelegate(Add);

            myDelegate += Subtract;

            myDelegate += Multiply;

            myDelegate += Devide;



            int result = Count(10, 20, myDelegate);

            Console.WriteLine("结果是:{0}", result);



            Console.ReadKey();

        }

    }

 运行结果为

C#深入浅出 C#语法中的重中之重——委托(四)

 

由运行结果分析,当一个委托引用同时指向多个符合方法标识的方法时,此时即构成多播委托。其本质是对System.MulticastDelegate类(为System.Delegate的子类)的继承和实现。由于一个委托只能有一个返回值,故一般多播委托为void的(并非一定),若有返回值,则最终的返回结果及多播系列中最后一个方法的返回值。

当多播委托的引用只指向一个方法,则其使用方法与单播委托一样,但是若指向多个方法,则除第一个使用=,其他均用+=。注意这里,第一次用的“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。例如:

MathDelegate myDelegate = new MathDelegate(Add);

            myDelegate += Subtract;

            myDelegate += Multiply;

            myDelegate += Devide;

 

既然一个委托可以绑定方法,就有办法取消对方法的绑定,很容易想到这个语法:-=

//第三种方式:多播委托

            MathDelegate myDelegate = new MathDelegate(Add);

            myDelegate += Subtract;

            myDelegate += Multiply;

            myDelegate += Devide;

            myDelegate -= Devide;//注意这里的写法

 由上个例子改写运行结果:

C#深入浅出 C#语法中的重中之重——委托(四)

我们看到除法没有了,是因为解除了对除法的绑定,最后一个方法是乘法,返回的结果是最后一个方法的运算结果。

你可能感兴趣的:(C#)