• C# 中的委托


    C# 中的委托

    委托定义

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

    • 委托是一种引用类型,所以它具有引用类型所具有的通性。它保存的不是实际值,而是保存对存储在托管堆中对象的引用。那它保存的是对什么的引用呢?委托保存的是对函数的引用

    • 简单来说委托就是封装了方法的变量

    • 任何委托都继承自System.MulticastDelegate。

    • .NET中的委托是类型安全的,委托会检测它所保存的函数引用是否和声明的委托匹配。

    委托的好处

    1.相当于用方法作为另一方法参数(类似于C的函数指针)

    2.在两个不能直接调用的方法中作为桥梁,如:在多线程中的跨线程的方法调用就得用委托

    3.当不知道方法具体实现什么时使用委托,如:事件中使用委托

    委托声明

    public delegate int Calculation(int x, int y);
    
    • 1

    委托使用

            public delegate int Calculation(int x, int y);
            //为委托创建一个加法计算方法
            public static int AddMethod(int x, int y)
            {
                int result = x + y;
                return result;
            }
    
            //为委托创建一个乘法计算方法
            public static int MulMethod(int x, int y)
            {
                int result = x * y;
                return result;
            }
            
            static void Main(string[] args)
            {
                //将加法计算方法赋值给委托
                Calculation cal = AddMethod;
                //调用委托
                int add = cal(1, 2);
    
                //将乘法计算方法绑定同一个委托
                cal += MulMethod;
                //调用委托
                int mul = cal(1, 2);
                
                //将乘法计算方法删除
                cal -= MulMethod;
                //调用委托
                int result = cal(1, 2);
                
                Console.WriteLine($"计算结果:{add}");
                Console.WriteLine($"计算结果:{mul}");
    			Console.WriteLine($"计算结果:{result }");
                Console.ReadKey();
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    输出结果:

    计算结果:3
    计算结果:2
    计算结果:3

    以上示例可以看出委托的一个特性:可以将方法赋值给同一个委托,或者将多个方法绑定到同一个委托,当调用这个委托时候,将依次调用其所绑定的方法

    注意第一次用的“=”是赋值的语法第二次,用的是“+=”是绑定的语法。如果第一次就使用“+=”。将出现“使用了未赋值的局部变量”的编译错误。
    同理如果要删除调用列表中的方法,请使用 “-” 或 “-=” 运算符。

    为什么委托定义的返回值通常都为 void ?

    尽管并非必需,但是我们发现很多的委托定义返回值都为 void,为什么呢?这是因为委托变量可以供多个订阅者注册,如果定义了返回值,那么多个订阅者的方法都会向发布者返回数值,结果就是后面一个返回的方法值将前面的返回值覆盖掉了,因此,实际上只能获得最后一个方法调用的返回值。可以运行上面的代码测试一下。除此以外,发布者和订阅者是松耦合的,发布者根本不关心谁订阅了它的事件、为什么要订阅,更别说订阅者的返回值了,所以返回订阅者的方法返回值大多数情况下根本没有必要。

    .NET自带的泛型委托类型(强类型委托)

    • Func< TResult >。用于有返回值的方法。(参数可有可无,至少0个参数,最多16个参数)
      按照约定,TResult结果的类型始终是所有 Func 声明中的最后一个类型参数。

    有返回值的委托类型的泛型委托类型:

    public delegate TResult Func<out TResult>();
    public delegate TResult Func<in T1, out TResult>(T1 arg);
    public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
    ...
    
    • 1
    • 2
    • 3
    • 4

    使用例子:

            static void Main(string[] args)
            {
            	//实例化Func委托
            	Func<int> func = new Func<int>(GetNumValue);
            	Func<int> func = GetNumValue;
            	
            	//将lambda表达式分配给Func委托
                Func<int> func = () => GetNumValue();
                
                //将匿名方法分配给Func委托
                Func<int> func = delegate () { return GetNumValue(); };
                
                Console.WriteLine($"计算结果:{func()}");
    
                Console.ReadKey();
            }
    
            static int GetNumValue()
            {
                return 1;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • Action< T >。用于无返回值的方法。(参数可有可无,至少0个参数,最多16个参数)
      对任何具有 void 返回类型的委托类型使用一种 Action 类型。
    public delegate void Action();
    public delegate void Action<in T>(T arg);
    public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
    ...
    
    • 1
    • 2
    • 3
    • 4
    • Predicate< T >,此类型返回单个值的测试结果
    public delegate bool Predicate<in T>(T obj);
    
    • 1
  • 相关阅读:
    力扣每日一题66:加一
    webstorm HbuilderX工具未配置
    Spring学习第2篇:IoC控制反转 与 DI依赖注入
    RabbitMQ 镜像集群部署
    【文生图系列】基础篇-马尔可夫链
    Segmentation-Based Deep-Learning Approach for Surface-Defect Detection-论文阅读笔记
    JavaSe-JAVA的多态
    解锁知识管理3.0,生成式人工智能洞察新时代
    4.云原生-KubeSphere中安装GitLab(三)
    蓝桥杯决赛PREV-392试题3:信用卡号的验证(第一届)
  • 原文地址:https://blog.csdn.net/qq_35434967/article/details/127824421