19-委托

作者: D丝学编程 | 来源:发表于2021-04-12 14:16 被阅读0次

    C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。

    委托(Delegate) 是存有对某个方法的引用的一种引用类型变量 。

    现实世界中的委托:

    自己动手模式:


    0001.PNG

    委托模式:一种类型的委托


    0002.PNG
    委托模式:多种类型的委托
    0003.PNG

    一、C#内置委托

    (1)Action委托:用于调用无参数,无返回值的函数。

    class OASystem
    {
        public void WelComeChinese()
        {
            Console.WriteLine("您好,欢迎来到******系统!");
        }
        public void WelComeEnglish()
        {
            Console.WriteLine("Hello, welcome to the ****** system!");
        }
    }
    
    static void Main(string[] args)
    {
        //直接调用
        //OASystem oa = new OASystem();
        //oa.WelComeChinese();
        //oa.WelComeEnglish();
        //委托调用
        OASystem oa = new OASystem();
        Action action1 = new Action(oa.WelComeChinese);
        Action action2 = new Action(oa.WelComeEnglish);
        action1();       //或action1.Invoke();
        action2();      //或action2.Invoke();
    }
    

    (2)Func委托:一种泛型委托,Func有一系列的重载。

    class Calculator
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
        public int Sub(int a, int b)
        {
            return a - b;
        }
        public int Mul(int a, int b)
        {
            return a * b;
        }
        public int Div(int a, int b)
        {
            return a / b;
        }
    }
    
    static void Main(string[] args)
    {
        //直接调用任意一种运算
        //Calculator cal = new Calculator();
        //int result = cal.Add(1, 2);
        //Console.WriteLine(result);
    
        Calculator cal = new Calculator();
        Func<int, int, int> func = new Func<int, int, int>(cal.Add);
        int result = func(1, 2);     //或func.Invoke(1, 2);
        Console.WriteLine(result);
    }
    

    (3)Predicate:一个传入参数,返回值为bool。

    class MyDate
    {
        //判断年份是否是闰年
        public bool Is29(int year)
        {
            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
                return true;
            else
                return false;
        }
        //判断是否需要工作(星期一到星期五需要工作,周六周日不需要)
        public bool IsWork(DateTime date)
        {
            if ((int)date.DayOfWeek == 0 || (int)date.DayOfWeek == 6)
                return false;
            else
                return true;
        }
    }
    
    static void Main(string[] args)
    {
        //直接调用两个方法
        //bool result = false;
        //MyDate myDate = new MyDate();
        //result = myDate.Is29(2020);
        //Console.WriteLine("闰年:"+result);
        //result = myDate.IsWork(new DateTime(2020, 7, 3));
        //Console.WriteLine("工作:"+result);
    
        //委托调用两个方法
        bool result = false;
        MyDate myDate = new MyDate();
        Predicate<int> pre1 = new Predicate<int>(myDate.Is29);
        result = pre1(2020); //或result = pre1.Invoke(2020);
        Console.WriteLine("闰年:" + result);
        Predicate<DateTime> pre2 = new Predicate<DateTime>(myDate.IsWork);
        result = pre2(new DateTime(2020, 7, 3)); //或result = pre2.Invoke(new DateTime(2020, 7, 3));
        Console.WriteLine("工作:" + result);
    }
    

    二、自定义委托及委托的多播(组播)

    class Calculator
    {
        public int Num { get; set; }
        public void Add(int n)
        {
            this.Num += n;
        }
        public void Sub(int n)
        {
            this.Num -= n;
        }
        public void Mul(int n)
        {
            this.Num *= n;
        }
        public void Div(int n)
        {
            this.Num /= n;
        }
    }
    
    delegate void ChangeNum(int n);
    class Program
    {
        static void Main(string[] args)
        {
            //自定义委托调用函数方法
            //Calculator cal = new Calculator();
            //cal.Num = 100;
            //ChangeNum cnAdd = new ChangeNum(cal.Add);
            //cnAdd(10);
            //Console.WriteLine(cal.Num);
    
            //委托的多播(组播)
            //相同类型的委托被合并,可以创建一个委托被调用时要调用的方法的调用列表
            Calculator cal = new Calculator();
            cal.Num = 100;
            ChangeNum cnAdd = new ChangeNum(cal.Add);
            ChangeNum cnSub = new ChangeNum(cal.Sub);
            ChangeNum cnMul = new ChangeNum(cal.Mul);
            ChangeNum cnDiv = new ChangeNum(cal.Div);
    
            ChangeNum cn = cnAdd;
            cn += cnMul;
            cn += cnSub;
            cn(50);
            Console.WriteLine(cal.Num);
        }
    }
    

    三、委托作为参数传递

    手机类:

    class Phone  //手机
    {
        public string Name { get; set; }  //手机名字
    }
    

    包装盒类:

    class Box  //包装盒
    {
        public Phone MyPhone { get; set; } //手机
    }
    

    手机生产工厂类:

    class PhoneFactory
    {
        public Phone MakeXiaoMi()
        {
            Phone phone = new Phone();
            phone.Name = "小米手机";
            return phone;
        }
        public Phone MakeHuawei()
        {
            Phone phone = new Phone();
            phone.Name = "华为手机";
            return phone;
        }
    }
    

    包装生产工厂类:

    delegate Phone MakePhone();
    class WrapFactory
    {
        #region 为每种手机进行包装盒工作-常规写法
        //包装小米手机
        public Box WarpXiaoMi()
        {
            PhoneFactory phoneFactory = new PhoneFactory();
            Phone phone = phoneFactory.MakeXiaoMi();
            Box box = new Box();
            box.MyPhone = phone;
            return box;
        }
        //包装华为手机
        public Box WarpHuawei()
        {
            PhoneFactory phoneFactory = new PhoneFactory();
            Phone phone = phoneFactory.MakeHuawei();
            Box box = new Box();
            box.MyPhone = phone;
            return box;
        }
        #endregion
    
        #region 将委托作为参数
        public Box WarpPhone(MakePhone mp)
        {
            Phone phone = mp();
            Box box = new Box();
            box.MyPhone = phone;
            return box;
        }
        #endregion
    }
    

    Main函数:

    static void Main(string[] args)
    {
        #region 生产并包装两个手机-常规写法
        //WrapFactory wrapFactory = new WrapFactory();
        //Box box1 = wrapFactory.WarpXiaoMi();
        //Console.WriteLine(box1.MyPhone.Name + "生产及包装已经完成!");
        //Box box2 = wrapFactory.WarpHuawei();
        //Console.WriteLine(box2.MyPhone.Name + "生产及包装已经完成!");
        #endregion
    
        #region 生产并包装两个手机-委托作为参数
        PhoneFactory phoneFactory = new PhoneFactory();
        MakePhone makeXiaomi = new MakePhone(phoneFactory.MakeXiaoMi);
        MakePhone makeHuawei = new MakePhone(phoneFactory.MakeHuawei);
        WrapFactory wrapFactory = new WrapFactory();
        Box box1 = wrapFactory.WarpPhone(makeXiaomi);
        Console.WriteLine(box1.MyPhone.Name + "生产及包装已经完成!");
        Box box2 = wrapFactory.WarpPhone(makeHuawei);
        Console.WriteLine(box2.MyPhone.Name + "生产及包装已经完成!");
        #endregion
    }
    

    四、利用委托实现匿名函数回调

    delegate void CallBackDelegate(int score);
    class Student
    {
        public string Name { get; set; } //姓名
        public string Mail { get; set; } //邮箱
        public int Score { get; set; } //分数
        public void Exam(CallBackDelegate callback = null)
        {
            Console.WriteLine("请填写姓名:");
            this.Name = Console.ReadLine();
            Console.WriteLine("请填写邮箱:");
            this.Mail = Console.ReadLine();
    
            Random rnd = new Random();
            this.Score = rnd.Next(0, 101);
            Console.WriteLine("该学生面试成绩为:" + this.Score);
            if (callback != null)
            callback(this.Score);
        }
    }
    
    static void Main(string[] args)
    {
        //Student stu = new Student();
        //CallBackDelegate myDelegate = delegate (int score)
        //{
        //    if (score >= 60)
        //        Console.WriteLine("已经给" + stu.Name + "的邮箱:"
        //            + stu.Mail + "发送了录用入职邀请!");
        //    else
        //        Console.WriteLine("很遗憾,我们不能录用您!");
        //};
        //stu.Exam();   //无参数调用
        //stu.Exam(myDelegate);  //有参数调用
    
        Student stu = new Student();
        //stu.Exam();
        //或
        stu.Exam((score) =>
        {
            if (score >= 60)
                Console.WriteLine("已经给" + stu.Name + "的邮箱:" + 
                    stu.Mail + "发送了录用入职邀请!");
            else
                Console.WriteLine("很遗憾,我们不能录用您!");
        });
    }
    

    五、委托与事件

    class EventTest
    {
        public delegate void MyEventHandler();
        public event MyEventHandler ValueChanged;
    
        private int value;
        public int Value
        {
            get
            {
                return value;
            }
            set
            {
                ValueChanged();
                this.value = value;
            }
        }
    }
    
    static void Main(string[] args)
    {   
        EventTest et = new EventTest();
        et.ValueChanged += new EventTest.MyEventHandler(myEventFunction);
        et.Value = 100;
        et.Value = 200;
    }
    public static void  myEventFunction()
    {
        Console.WriteLine("value值在发生改变!");
    }
    

    相关文章

      网友评论

          本文标题:19-委托

          本文链接:https://www.haomeiwen.com/subject/emzlxltx.html