• 说说委托是个什么东西,以及委托有什么用


    说说委托是个什么东西,以及委托有什么用

    定义:委托是一种知道如何调用方法的对象

    // 定义一个委托,这个委托定义了通过此委托调用的方法必须是接收一个字符串参数,返回int类型
    delegate int OneDelegate(string s);
    
    // 委托是一个对象,所以在使用委托时也需要创建实例
    OneDelegate one = null;
    

    委托是一个帮手,是一个集合

    先说委托是什么东西,委托是一个帮手,是一个集合,为什么这么说呢,因为它就是这么用的

    结合实际例子来说

    // 这是一个简单的例子,我们从请假的角度来说委托
    using System;
    
    //定义一个委托对象,这个委托定义了通过此委托调用的方法必须是接收一个字符串参数,没有返回值(返回类型为void)
    delegate void LeaveDelegate(string s);
    
    class Program
    {
        static void Main(string[] args)
        {
            Student b = new Student("蓝精灵"); // 创建学生实例蓝精灵
            // b调用请假方法,传递一个委托
            b.Leave(Teachers.OneStudentLeave); // 直接传递一个满足委托要求的方法,相当于实例化一个委托变量并将方法注册到这个委托变量再传递给Leave方法
        }
    }
    
    class Student
    {
        private readonly string _name;
    
        public Student(string name)
        {
            _name = name;
        }
        // 请假,需要一个委托形参
        public void Leave(LeaveDelegate e)
        {
            e(_name);
        }
    }
    // 老师类
    class Teachers
    {
        // 登记请假
        public static void OneStudentLeave(string name)
        {
            // 学生请假
            Console.WriteLine(name +"我已收到你的请假申请");
    
            // 一个简单例子,忽略数据库操作
        }
    }
    
    

    为什么用委托

    在这个例子中,Leave方法调用委托,委托调用OneStudentLeave方法,这种间接调用的方式将调用者和目标方法解耦,解耦之后更有利于单元测试,不用一定等到老师的请假方法写好了才能测试学生的Leave的方法是否正确;在需求改动的时候,也无需再对Leave方法进行修改

    能用委托的也可以用接口,但以下情况建议使用委托

    • 接口内仅定义了一个方法
    • 需要多播能力
    • 订阅者需要多次实现接口

    满足以上条件一个或多个时建议使用委托,因为在以上任意一种情况下,使用接口的代码量会远远超过使用委托,并且可维护性也不如使用委托,如果有疑问可以把本文中的例子用接口实现一遍,便能够明白

    多播委托更强大

    所有的委托实例都拥有多播能力。这意味着一个委托可以引用任意个方法,在之前的例子中,委托只引用了一个方法,假设现在请假除了要告知老师,还要告知校长,那么我们的代码会有多少变化?

    using System;
    
    //定义一个委托对象,这个委托定义了通过此委托调用的方法必须是接收一个字符串参数,没有返回值(返回类型为void)
    delegate void LeaveDelegate(string s);
    
    class Program
    {
        static void Main(string[] args)
        {
            Student b = new Student("蓝精灵"); // 创建学生实例蓝精灵
    
            // 声明一个委托变量e,将Teachers.OneStudentLeave方法添加到引用
            LeaveDelegate e = Teachers.OneStudentLeave;
            // President.OneStudentLeave方法添加到引用e
            // 此时e保存了两个方法的引用
            e += President.OneStudentLeave;
            
            // b调用请假方法,传递一个委托
            b.Leave(e); 
        }
    }
    
    class Student
    {
        private readonly string _name;
    
        public Student(string name)
        {
            _name = name;
        }
        // 请假,需要一个委托形参
        public void Leave(LeaveDelegate e)
        {
            e(_name);
        }
    }
    // 老师类
    class Teachers
    {
        // 登记请假
        public static void OneStudentLeave(string name)
        {
            // 学生请假
            Console.WriteLine(name +"我已收到你的请假申请");
    
            // 一个简单例子,忽略数据库操作
        }
    }
    
    class President
    {
        public static void OneStudentLeave(string name)
        {
            Console.WriteLine(name + "我同意了你的请假");
        }
    }
    
    

    这是使用了多播委托的情况,面对增加向校长请假的需求变更,新增了校长类,然后将校长的OneStudentLeave方法注册到委托中,没有修改老师类,也没有修改学生类,也没有因为需要向多个人申请而添加新的方法

    何必自己定义委托

    自从C# 2.0之后,C#有了Func委托和Action委托

    这两个委托是Framework提前定义好的,我们可以直接拿来用

    Action委托可以接收0到16个参数的方法

    Func委托也可以接收0到16个参数的方法,但是必须有一个返回值

    有没有觉得很神奇,ActionFunc都是不限制方法类型的,其实,这是因为它们都是泛型委托,委托也可以是泛型的,所以它们可以是接收任意类型的方法

    而接收0到16个参数,是因为它们有多个重载版本,Framework都给我们写好了,一般情况下,ActionFunc就足够我们使用了,几乎遇不上自己声明委托的情况了

    委托相等

    当比较两个委托是否相等时,并不是比较它的参数和返回类型,而是比较它们注册的方法,如果两个委托实例中注册的方法一模一样,那么这两个委托实例相等,否则不相等

  • 相关阅读:
    IEnumerable、ICollection、IList、List关系和区别
    在Winform界面中使用DevExpress的TreeList实现节点过滤查询的两种方式
    关键字Lock的简单小例子
    .NET Core DI简单介绍
    Linux服务器部署.Net Core笔记:六、安装MySQL
    表的透视变换
    ZedGraph怎样在生成曲线时随机生成不一样的颜色
    3、手写Unity容器--第N层依赖注入
    微信支付-小程序H5 公众号 Payment SDK
    WPF继续响应被标记为已处理事件的方法
  • 原文地址:https://www.cnblogs.com/wujuncheng/p/13392057.html
Copyright © 2020-2023  润新知