C# 面向对象之委托与事件

一、 什么是委托 ?

委托代表的是方法,委托是一种数据类型,当调用委托时就是调用了这个方法。

解释:委托是一类行为抽象,是方法的引用,存储了方法的地址。

             委托是一种数据类型【声明了返回类型和参数组成】

           委托可以实现对方法的【间接】调用! 灵活=维护性好!

              委托代表的是方法 【代表和委托签名一致的任何方法】

签名 含义不同 有时1:  签名=返回类型和参数组成

              有时2:签名=方法名和参数组成【隐藏】

              有时3:签名=方法名和参数组成,返回类型【重写!】

注意:

委托的使用步骤:三步  1:定义端 2:实例化委托(多种写法) 3:调用端

 二、 实例化委托多种写法 :

 方式一、基本传统标准的写法,适合于: 委托已有的方法。 

步骤1【定义端】:义委托

          delegate 返回值 方法签名;

例如:delegate void Handler(); 习惯命名:方法后加Handler:SelectHandler

步骤2【调用端】:创建实例

实例化委托:为委托指定{绑定}方法,方法名】

Handler handler = new Handler(Fun);等号右边表示的是委托对象,委托不是方法

步骤3【调用端】:调用委托【和调方法相似,有参数就要写参数,有返回值可以返回】 

   handler();

   public static void Fun() { }

方式二、基本传统标准简化写法,写法一的简化,适合于: 委托已有的方法

注意:方式一、二一定要先写好方法再绑定委托

下面介绍实例化委托的其他两种常用写法:

 方式三、匿名方法,适合于功能简单少量代码可以完成,且该功能不需要在其它地方复用.

               匿名方法本质是委托对象,没有名字

 

方式四、Lambda 表达式

     写法一:功能简单少量代码可以完成,且该功能不需要在其它地方复用

       Lambda 表达式语法

                    委托类型 委托对象名=Lambda 表达式;

                    写法一   :    (参数)=>{语句}    => 读作goto

                    (参数1,参数2)=> 一行代码;注意:方法有返回值的时候return不能写!

                    简化写法二 :当参数是一个,语句是一句话的时候小括号大括号可以省略:

                      一个参数=>一行代码return不能写!

                   Handler  handler = (p) => Console.WriteLine(p + "HAHA");

                   等号右边 表示的是委托对象=Lambda 表达式=匿名方法

    Lambda表达式写法二:功能代码超简单,一行代码可以完成

注意:方式三、四不需要写好方法,心中定义好

三、练习:实例化以下的委托 使用4种方法实例化完成 

public int Handler(Person p) //从一个对象中选一个属性 Person id或age

public Person Handler(List< Person > list,int id)//从一个集合中选择编号=id的那个对象

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

namespace DemoDelegate444
{
    //
    class EX4
    {
        static void Main()
        { 
              
            //2> 4种写法
            //Handler handlerObj = new Handler(Fun);//111
            //Handler handlerObj = Fun;//222
            //Handler handlerObj = delegate(List<Person> list, int id)
            //{
            //    Person person = null;
            //    foreach (var p in list)
            //    {
            //        if (p.Id == id)
            //        {
            //            person = p;
            //            break;
            //        }
            //    }
            //    return person;
            
            //};
            Handler handlerObj = (list, id) =>
            {
                Person person = null;
                foreach (var p in list)
                {
                    if (p.Id == id)
                    {
                        person = p;
                        break;
                    }
                }
                return person;
            
            }; //444
            
            //3>  
            List<Person> arr = new List<Person> 
            { 
                new Person(){Id = 1,Name = "aa",Age = 20},
                new Person(){Id = 2,Name = "bb",Age = 22}
            };
            var re = handlerObj(arr, 2);

        }
        //static Person Fun(List<Person> list, int id)
        //{
        //    Person person = null;
        //    foreach (var p in list)
        //    {
        //        if (p.Id == id)
        //        {
        //            person = p;
        //            break;
        //        }
        //    }
        //    return person;
        //}
    }
    //定义端 1>
   public  delegate  Person Handler(List< Person> list,int id);
    //从一个集合中选择编号=id的那个对象
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

}

四、委托的分类 调用【使用】方式

1单播委托:一个委托对象只关联一个方法

2多播执行:一个委托对象关联多个方法 只返回最后方法的结果

                所以:委托有返回值不适合多播执行!适合单播执行。

                      委托无返回值适合多播执行

委托是数据类型

五、委托的作用 用途 实际应用!

   1》、将方法做为参数传递,可以将一个方法的执行代码注入到另一个方法中。

                 为什么要注入?

1、定义算法/方法时 :有的语句/步骤能定下来,有的暂时定不下来,可以使用委托表示确定不下来的

 2、调用时再确定 把有些功能推迟到客户端【调用端】确定!

2》、实现回调,实现的方式比接口更灵活

回调最早的含义1: 方法或函数由 系统调用 【不是程序员直接调用的】

       含义 2 这里的含义  定义方法 有些定义时确定不下来,留给客户端确定

          调用时候,从 调用端 到定义端

          到调用端 再到定义端执行 【灵活性】

          回到调用端,结束

       举个例子: 比如回家紧接着做什么事情。回家是唯一,能确定的    做的什么事情是不确定的【复习,看电视,玩游戏,聊天】

     解决方案1:

解决方案2:对于变化的提取出来单独封装【接口】,接口作为参数,也会造成代码的膨胀

 

解决方案3:使用委托做参数不会造成代码的膨胀

       举这个例子想要说明得是:

  1. 接口可以作为方法的参数!
  2. 委托可以作为方法的参数

    同样可以作为方法参数;委托可以实现回调,比接口更灵活.

 

发布了152 篇原创文章 · 获赞 24 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_40229737/article/details/104031854