黑马程序员---委托(delegate)的进一步理解

来源:互联网 发布:大数据研发工程师招聘 编辑:程序博客网 时间:2024/05/18 12:35

---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------

    委托只是一种特殊的类型,它包含的只是方法的地址;
    假如在某个方法中需要另一个方法怎么办?委托就能帮我们解决这个问题,它可以作为某个方法的参数传入;

来看一下的例子及代码和注释:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 委托delegate的进一步理解
{
    class Program
    {
        static void Main(string[] args)
        {
            //注意实例化时的委托参数(也就是方法)不要带括号
            ReturnValue r1 = new ReturnValue(ClassMethod.Method1);  //实例化一个委托,使用静态方法做为参数
            //ReturnValue r2 = ClassMethod.Method1;  //其实这样写也是可以实例委托的,委托不就是方法的容器嘛
            ReturnValue r3 = new ClassMethod().Method2;  //也可以使用实例方法作为参数,都可以
            ReturnValue r4 = delegate(double v)
            {
                return 2 * v;
            };  //也可以使用匿名方法来实例委托

            //我们把ClassMethod.Method1()方法传入ClassMethod.ShowValue方法中
            ClassMethod.ShowValue(r1, 5.5); 
            //多播委托(委托链),上面介绍的委托都只包含一个方法,调用的次数与调用方法的次数相同;其实委托是可以
            //包含多个方法的,但是一定要注意,包含多个方法的委托返回值为void,否则只能得到委托调用的最后一个
            //方法的结果(可以使用运算符"+、-、+=、-=")
            ReturnValue rr = r1 + r3;
            //得到的只是最后一个方法的结果,而不是我们想要的两个结果,原因就是委托的返回值不为void
            ClassMethod.ShowValue(rr, 2.5); 

            //要想得到多个方法的结果,我们因此要重新定义委托及方法,让它们都返回void
            ReturnVoid r11 = ClassMethod.Method11;
            ReturnVoid r22 = new ClassMethod().Method22;
            ReturnVoid r33 = delegate(double value)
            {
                Console.WriteLine("传入的值为{0},结果为{1}", value, 2 * value);
            };
            ReturnVoid rs = r11 + r22 + r33;
            ClassMethod.ShowValue1(rs, 10.5); //这样我们就可以都得到每个方法的结果了

            /*但是多播委托有一个致命的问题,那就是如果前面方法有一个抛出异常,则整个迭代就停止;
            解决的方法是使用delegate类的方法GetInvocationList(),它返回一个Delegate对象数组*/
            ReturnVoid rE = ClassMethod.ThrowException;
            ReturnVoid rsException = rE + rs;
            //执行到第一个方法的时候就抛出异常,迭代也就停止了
            //try
            //{
            //    ClassMethod.ShowValue1(rsException, 1.5);
            //}
            //catch (Exception ee)
            //{
            //    Console.WriteLine(ee.Message);
            //}

            //解决方法:
            Delegate[] delegates = rsException.GetInvocationList();
            //抛出异常后还是能够执行下去
            foreach (ReturnVoid rvs in delegates)
            {
                try
                {
                    ClassMethod.ShowValue1(rvs, 2.4);
                }
                catch(Exception ee)
                {
                    Console.WriteLine(ee.Message);
                }
            }
            Console.ReadKey();
        }
    }
    //定义一个委托
    delegate double ReturnValue(double d);
    //重新定义返回void的委托
    delegate void ReturnVoid(double d);
    class ClassMethod
    {
        //静态方法
        public static double Method1(double value)
        {
            value = value * 10;
            return value;
        }
        public static void Method11(double value)
        {
            Console.WriteLine("传入的值为{0},结果为{1}",value,10 * value);
        }

        //我们在这里定义一个方法,并且抛出异常
        public static void ThrowException(double b)
        {
            throw new Exception("抛出异常ThrowException方法");
        }
        //实例方法
        public double Method2(double value)
        {
            value = value * value;
            return value;
        }
        public void Method22(double value)
        {
            Console.WriteLine("传入的值为{0},结果为{1}",value,value * value);
        }
        //其实这里委托作为参数就是传入方法,以前我们的参数都是预定义类型及自己定义的类
        public static void ShowValue(ReturnValue rv,double value)
        {
            double result = rv(value);
            Console.WriteLine("传入的值为{0},结果为{1}", value, result);
        }
        public static void ShowValue1(ReturnVoid rv, double value)
        {
            rv(value);
        }
    }
}

---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------

原创粉丝点击