C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。在C#中方法不能作为参数直接传递,必须使用委托(用来委托方法)。delegate(委托)是一种特殊的引用类型,它将方法也作为特殊的对象封装起来,从而将方法作为变量、参数或者返回值传递。委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。使用一个委托有三个步骤:

定义委托
实例化委托
将指定的方法添加到委托对象中
例子:
        delegate int plus(int x, int y); // 1. 定义委托
 
        static void Main(string[] args)
        {
            plus del_p;  // 2. 实例化委托
 
            del_p = new plus(addition);  // 3. 将方法添加到实例化委托对象中
 
            int n = del_p(1, 2);
            Console.Write(n);
        }
 
        static int addition(int x, int y)
        {
            return x + y;  
        }

C#允许直接把方法名赋给委托,所以下面的三种写法也正确:

plus del_p = new plus(addition);
            plus del_p2 = addition;
            del_p = addition;

委托完全可以被当做普通类型对待,比如可以加减、赋值、构建数组。
委托数组
委托可以构建数组,意味着一组同样返回类型和参数类型的方法。
        delegate int MathFunc(int x, int y); 
 
        static void Main(string[] args)
        {
            MathFunc[] fs = new MathFunc[]
            {
                substract, 
                addition, 
                product,
                division
            };
 
            int n = fs[0](1, 2); // -1
        }
 
        static int division( int x, int y)
        {
            return x / y;
        }
 
        static int substract(int x, int y)
        {
            return x - y; 
        }
 
        static int addition(int x, int y)
        {
            return x + y;  
        }
 
        static int product(int x, int y)
        {
            return x * y;
        }

委托的加减法/委托的多播(Multicasting of a Delegate)
一个委托对象可以封装多个方法,通过委托对象的合并(加法)实现。被合并的方法必须有相同的返回类型和参数类型。使用合并后的委托时,会依次将实参传入被合并的方法,最后的返回值以最后一个方法为准。
        delegate int MathFunc(int x, int y); 
 
        static void Main(string[] args)
        {
            MathFunc f;
            f = addition;
            f += substract;
            f += product;
            int n = f(1, 2); // 2
        }
 
        static int division( int x, int y)
        {
            Console.WriteLine("division");
            return x / y;
        }
 
        static int substract(int x, int y)
        {
            Console.WriteLine("substraction");
            return x - y; 
        }
 
        static int addition(int x, int y)
        {
            Console.WriteLine("addition");
            return x + y;  
        }
 
        static int product(int x, int y)
        {
            Console.WriteLine("product");
            return x * y;
        }
上面的代码会打印出:

addition 
substraction 
product

委托减法是加法的逆运算。如果被减委托中不含有减数委托,则不会对被减数造成任何影响,被减数减去自身为null,调用空委托会引发异常。总结下来委托加减法的几个结论:
委托加减null没有任何效果
委托减自身为null
减数如果没有包含在被减数中,则没有任何效果
在使用委托之前,应该判断委托是否为null。

传递委托
委托可以被作为以下方式传递
变量
方法参数
方法返回值
        delegate int MathFunc(int x, int y); 
 
        static void Main(string[] args)
        {
            MathFunc f = getAddFunc();
            int n = f(2, 3); // 5
            int n2 = add(f, 3, 4); // 7
        }
 
        static int add(MathFunc f, int x, int y)
        {
            return f(x,  y);
        }
 
        static MathFunc getAddFunc()
        {
            return addition;
            // or return new MathFunc(addition);
        }

匿名方法(delegate方法)
使用 delegate 关键字直接定义方法,和实例化委托不同,不使用 new 关键字来创建委托对象,而是直接定义方法参数和方法体。匿名方法并不是真的没有名称,而是指程序员无需命名。C#在编译时会给方法生成一个方法定义(包含方法名和参数列表),该方法实际上是当前类型的一个私有静态方法。
        delegate int MathFunc(int x, int y); 
 
        static void Main(string[] args)
        {
            MathFunc f = delegate (int x, int y)
            {
                return x + y;
            };
            int n = f(1, 2); // 3
        }
Lambda表达式
从C# 3.0 开始,可以用 lambda表达式替换匿名方法表达式,直接将一个 Lambda表达式赋给委托对象。注意Lambda表达式不能作为语句,必须为右值。Lambda表达式的参数和返回类型必须和委托一致。
        delegate int MathFunc(int x, int y); 
 
        static void Main(string[] args)
        {
            MathFunc f;
            f = (int x, int y) =>
            {
                return x + y;
            };
            int n = f(1, 2); // 3
        }
如果lambda表达式只有一个参数,则可以省略圆括号。Lambda表达式允许多种写法,以下写法等价:
            something = (int x, int y) => { return x + y; };
            something = (int x, int y) => x + y;
            something = (x, y) => x + y;
            something = (x, y) => { return x + y; }; 
Lambda表达式中没有用到的参数可以用 _ 代替。比如
something = (x, _) => x * 2;

在Lambda表达式和匿名delegate方法内部都可以访问主调函数的外部变量,比如:
            MathFunc f;
            string str = "str";
            f = (x, y) =>
            {
                Console.Write(str); // 访问了外部的str
                return x + y;
            };
如果Lambda表达式或者匿名delegate方法的参数名和外部变量冲突,则无法通过编译。
委托发布和订阅
基于委托多播的特性,可以实现 “发布者/订阅者”模式。发布者对象有一个委托成员,保存一系列别的类的实例(订阅者)的方法,一旦发布者触发(调用)了委托,就会把所有注册过的方法都依次调用依次,通知订阅者。比如有一个红绿灯,一旦红绿灯变色,就会通知所有车辆和行人,此时可以把车辆和行人的响应方法注册到红绿灯对象的一个 public 委托成员 OnColorChange 里,当红绿灯调用 OnColorChange 时,就会通知所有车辆,调用他们的响应函数。由于订阅者的类型和响应方法千奇百怪,可以高度定制针对一个事件(比如红绿灯变色)的不同对象的不同响应函数。
由于委托成员 OnColorChange 是公有的,一旦别的程序将委托置为空,或其他值,委托先前的修改就前功尽弃了。为了防止这种事情发生,C# 提供了 event 来修饰(声明)委托成员。经过 event 修饰后,委托成员只能被 += 和 -= 修改,而不能用 = 修改。
--------------------- 
作者:csdn_chai 
来源:CSDN 
原文:https://blog.csdn.net/csdn_chai/article/details/77429538 
版权声明:本文为博主原创文章,转载请附上博文链接!

【C#学习】delegate(委托) 和 event(事件)相关推荐

  1. 转:终于会用c#中的delegate(委托)和event(事件)了

    第一个例子: public class DelegateTest {// 声明delegate对象 public delegate void CompareDelegate(int a,int b); ...

  2. vue学习:事件传递(冒泡和捕获),事件委托,jquery中的事件委托,$event 获取元素,vue事件修饰符

    事件传递 ----冒泡和捕获 DOM事件标准定义了两种事件流,这两种事件流分别是捕获和冒泡. 和许多Web技 术一样,在它们成为标准之前,Netscape和微软各自不同地实现了它们.Netscape选 ...

  3. C#学习基本概念之关键字---delegate(委托)

    委托类型的声明与方法签名相似,  有一个返回值和任意数目任意类型的参数: public delegate void TestDelegate(string message); public deleg ...

  4. 学习笔记(30):Python网络编程并发编程-Event事件

    立即学习:https://edu.csdn.net/course/play/24458/296447?utm_source=blogtoedu threading.Event事件 1.概念及功能:主要 ...

  5. input回车触发事件_JavaScript学习笔记(十五)-- Event事件(上)

    EVENT(上) 之前我们简单的了解过一些事件,比如 onclick / onload / onscroll / ... 今天开始,我们详细的学习一些 事件 什么是事件 一个事件由什么东西组成 触发谁 ...

  6. Event事件-1:addEventListener事件监听 / 事件冒泡事件捕获 / 事件委托 / preventDefault 阻止默认行为 / cancelBubble、stopPropa...

    addEventListener 事件监听器 target.addEventListener(type, listener[, options|useCapture])     添加事件监听 参数: ...

  7. 基础才是重中之重~通过人类的生活来学习Delegate

    一个人(people),在他60岁之后,就宣布进入晚年了,在这个期间要多注意身体,多体检. namespace NET基础才是重中之重{/// <summary>/// 人类/// < ...

  8. 委托模型和事件模型 [C#]

    1. 多播委托     与委托有关的语法: 定义委托:<modifiers> delegate <return_type> <delegate_name> (< ...

  9. web api、获取DOM元素的方式、事件理解、click事件在移动端300ms延时、事件对象、事件委托、常见事件类型

    web api: API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力 ...

最新文章

  1. php 做积分策略,积分策略
  2. LeetCode之Power of Two
  3. 动态污点分析隐式流--动静结合的解决方法
  4. [iOS]通过xib定义Cell然后关联UICollectionView
  5. 【TDA4系列】CCS 最新版本安装与教程地址
  6. .NET编译工具(每日构建或自动化编译)
  7. python 伪原创 中文近义词工具包【转】
  8. delaunay三角网构建
  9. linux下面如何看抓包文件,linux抓包
  10. python实现屏幕截图_Python实现计算机屏幕任意区域截图
  11. ioncube php encode,ioncube加密与解密 php代码
  12. 量子计算机交叉学,人工智能与量子物理交叉研究 有多少激动人心的事
  13. 配置Windows通过腾讯云服务器远程Ubuntu系统
  14. qq企业邮箱创建过程
  15. Python数据处理工具——Pandas
  16. linux的crontab 命令,每三个月的月末执行一次
  17. 解决eclips代码批量首行缩进 退格 调试
  18. netstat -ano 查看端口是否被占用
  19. Android中的多线程编程与异步处理
  20. 一:tomcat的简介:

热门文章

  1. vlist java实现-转
  2. 机器学习算法基础(基础机器学习课程)——第一天
  3. Python做文本挖掘的情感极性分析
  4. 深度学习训练的小技巧,调参经验。总结与记录。
  5. Introduction to Machine Learning
  6. 58同城创始人姚劲波:未来十年是中国创业最好机会
  7. jvm性能调优实战 - 49OOM异常进行监控以及online处理
  8. MyBatis-07MyBatis注解方式之@Select
  9. Oracle优化06-Hint
  10. Oracle-PL/SQL基础