C#学习基本概念之关键字---delegate(委托)
委托类型的声明与方法签名相似, 有一个返回值和任意数目任意类型的参数:
public delegate void TestDelegate(string message); public delegate int TestDelegate(MyType m, long num);
delegate
是一种可用于封装命名或匿名方法的引用类型。 委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。 有关委托的应用,请参见委托和泛型委托。
委托是事件的基础。
通过将委托与命名方法或匿名方法关联,可以实例化委托。 有关更多信息,请参见命名方法和匿名方法。
必须使用具有兼容返回类型和输入参数的方法或 lambda 表达式实例化委托。 有关方法签名中允许的差异程度的更多信息,请参见委托中的变体。 为了与匿名方法一起使用,委托和与之关联的代码必须一起声明。 本节讨论这两种实例化委托的方法。
委托是事件的基础。
通过将委托与命名方法或匿名方法关联,可以实例化委托。 有关更多信息,请参见命名方法和匿名方法。
必须使用具有兼容返回类型和输入参数的方法或 lambda 表达式实例化委托。 有关方法签名中允许的差异程度的更多信息,请参见委托中的变体。 为了与匿名方法一起使用,委托和与之关联的代码必须一起声明。 本节讨论这两种实例化委托的方法。
delegate double MathAction(double num); class DelegateTest{ // Regular method that matches signature:static double Double(double input){ return input * 2;} static void Main(){ // Instantiate delegate with named method:MathAction ma = Double; // Invoke delegate ma:double multByTwo = ma(4.5);Console.WriteLine("multByTwo: {0}", multByTwo); // Instantiate delegate with anonymous method:MathAction ma2 = delegate(double input){ return input * input;}; double square = ma2(5);Console.WriteLine("square: {0}", square); // Instantiate delegate with lambda expressionMathAction ma3 = s => s * s * s; double cube = ma3(4.375);Console.WriteLine("cube: {0}", cube);} // Output:// multByTwo: 9// square: 25// cube: 83.740234375}
备注:摘自https://msdn.microsoft.com/zh-cn/library/900fyy8e.aspx
**************************************************
委托:
delegate 是表示对具有特定参数列表和返回类型的方法的引用的类型。 在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联。 你可以通过委托实例调用方法。
委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法。 你可以创建一个自定义方法,当发生特定事件时,某个类(如 Windows 控件)就可以调用你的方法。 下面的示例演示了一个委托声明:
public delegate int PerformCalculation(int x, int y);
可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。 该方法可以是静态方法,也可以是实例方法。 这样便能通过编程方式来更改方法调用,还可以向现有类中插入新代码。
在方法重载的上下文中,方法的签名不包括返回值。 但在委托的上下文中,签名包括返回值。 换句话说,方法和委托必须具有相同的返回类型。
将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。 例如,对比较两个对象的方法的引用可以作为参数传递到排序算法中。 由于比较代码在一个单独的过程中,因此可通过更常见的方式编写排序算法。
委托具有以下属性:
委托类似于 C++ 函数指针,但它们是类型安全的。
委托允许将方法作为参数进行传递。
委托可用于定义回调方法。
委托可以链接在一起;例如,可以对一个事件调用多个方法。
方法不必与委托类型完全匹配。 有关详细信息,请参阅在委托中使用变体。
C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递来代替单独定义的方法。 C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。 匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。 这些功能现在统称为匿名函数。 有关 lambda 表达式的更多信息,请参见 匿名函数。
使用委托
When to Use Delegates Instead of Interfaces (C# Programming Guide)
带有命名方法的委托与带有匿名方法的委托
匿名方法
在委托中使用变体
如何:合并委托(多路广播委托)
如何:声明、实例化和使用委
备注:摘自https://msdn.microsoft.com/zh-cn/library/ms173171.aspx
使用委托:
委托是安全封装方法的类型,类似于 C 和 C++ 中的函数指针。 与 C 函数指针不同的是,委托是面向对象的、类型安全的和可靠的。 委托的类型由委托的名称确定。 以下示例声明名为 Del
的委托,该委托可以封装采用字符串作为参数并返回 void 的方法:
public delegate void Del(string message);
委托对象通常通过提供委托将封装的方法的名称或使用匿名方法构造。 对委托进行实例化后,委托会将对其进行的方法调用传递到该方法。 调用方传递到委托的参数将传递到该方法,并且委托会将方法的返回值(如果有)返回到调用方。 这被称为调用委托。 实例化的委托可以按封装的方法本身进行调用。 例如:
public static void DelegateMethod(string message){System.Console.WriteLine(message);}
Del handler = DelegateMethod; // Call the delegate.handler("Hello World");
委托类型派生自 .NET Framework 中的 Delegate 类。 委托类型是封装的,它们不能派生出其他类,也不能从 Delegate 派生出自定义类。 由于实例化的委托是一个对象,因此可以作为参数传递或分配给一个属性。 这允许方法作为参数接受委托并在稍后调用委托。 这被称为异步回调,是在长进程完成时通知调用方的常用方法。 当以这种方式使用委托时,使用委托的代码不需要知道要使用的实现方法。 功能类似于封装接口提供的功能。
回调的另一个常见用途是定义自定义比较方法并将该委托传递到短方法。 它允许调用方的代码成为排序算法的一部分。 以下示例方法使用 Del
类型作为参数:
public void MethodWithCallback(int param1, int param2, Del callback){callback("The number is: " + (param1 + param2).ToString());}
然后,你可以将上面创建的委托传递到该方法:
MethodWithCallback(1, 2, handler);
并将以下输出接收到控制台:
The number is: 3
以抽象方式使用委托时,MethodWithCallback
不需要直接调用控制台,记住,其不必设计为具有控制台。 MethodWithCallback
的作用是简单准备字符串并将字符串传递到其他方法。 由于委托的方法可以使用任意数量的参数,此功能特别强大。
当委托构造为封装实例方法时,委托将同时引用实例和方法。 委托不知道除其所封装方法以外的实例类型,因此委托可以引用任何类型的对象,只要该对象上有与委托签名匹配的方法。 当委托构造为封装静态方法时,委托仅引用方法。 请考虑以下声明:
public class MethodClass{ public void Method1(string message) { } public void Method2(string message) { }}
加上之前显示的静态 DelegateMethod
,我们现在已有三个 Del
实例可以封装的方法。
调用时,委托可以调用多个方法。 这被称为多播。 若要向委托的方法列表(调用列表)添加其他方法,只需使用加法运算符或加法赋值运算符(“+”或“+=”)添加两个委托。 例如:
MethodClass obj = new MethodClass();Del d1 = obj.Method1;Del d2 = obj.Method2;Del d3 = DelegateMethod; //Both types of assignment are valid.Del allMethodsDelegate = d1 + d2;allMethodsDelegate += d3;
此时,allMethodsDelegate
的调用列表中包含三个方法,分别为 Method1
、Method2
和 DelegateMethod
。 原有的三个委托(d1
、d2
和 d3
)保持不变。 调用 allMethodsDelegate
时,将按顺序调用所有三个方法。 如果委托使用引用参数,引用将按相反的顺序传递到所有这三个方法,并且一种方法进行的任何更改都将在另一种方法上见到。 当方法引发未在方法内捕获到的异常时,该异常将传递到委托的调用方,并且不会调用调用列表中的后续方法。 如果委托具有返回值和/或输出参数,它将返回上次调用方法的返回值和参数。 若要删除调用列表中的方法,请使用减法运算符或减法赋值运算符(“+”或“+=”)。 例如:
//remove Method1allMethodsDelegate -= d1; // copy AllMethodsDelegate while removing d2Del oneMethodDelegate = allMethodsDelegate - d2;
由于委托类型派生自 System.Delegate
,因此可以在委托上调用该类定义的方法和属性。 例如,若要查询委托调用列表中方法的数量,你可以编写:
int invocationCount = d1.GetInvocationList().GetLength(0);
调用列表中具有多个方法的委托派生自 MulticastDelegate,该类属于 System.Delegate
的子类。 由于这两个类都支持 GetInvocationList
,因此在其他情况下,上述代码也将产生作用。
多播委托广泛用于事件处理中。 事件源对象将事件通知发送到已注册接收该事件的接收方对象。 若要注册一个事件,接收方需要创建用于处理该事件的方法,然后为该方法创建委托并将委托传递到事件源。 事件发生时,源调用委托。 然后,委托将对接收方调用事件处理方法,从而提供事件数据。 给定事件的委托类型由事件源确定。 有关详细信息,请参阅事件。
在编译时比较分配的两个不同类型的委托将导致编译错误。 如果委托实例是静态的 System.Delegate
类型,则允许比较,但在运行时将返回 false。 例如:
delegate void Delegate1(); delegate void Delegate2(); static void method(Delegate1 d, Delegate2 e, System.Delegate f){ // Compile-time error.//Console.WriteLine(d == e);// OK at compile-time. False if the run-time type of f // is not the same as that of d.System.Console.WriteLine(d == f);}
备注:转自https://msdn.microsoft.com/zh-cn/library/ms173172.aspx
转载于:https://blog.51cto.com/jiaojusuimu/1877126
C#学习基本概念之关键字---delegate(委托)相关推荐
- Csharp关键字----delegate(委托)
Delegate类简介 ------------------------ 命名空间:System 程序集:mscorlib(在 mscorlib.dll 中) 委托(Delegate)类是一 ...
- C#学习基本概念之关键字--abstract与sealed
1.abstract修饰符 abstract 修饰符指示所修饰的内容缺少实现或未完全实现. abstract 修饰符可用于类.方法.属性.索引器和事件. 在类声明中使用 abstract 修饰符以 ...
- 【C#学习】delegate(委托) 和 event(事件)
C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针.委托(Delegate) 是存有对某个方法的引用的一种引用类型变量.引用可在运行时被改变.在C#中方法不能作为参数直接传递,必须 ...
- delegate委托
delegate委托: 三个概念: C# 中的委托类似于 C 或 C++ 中的函数指针. 委托是面向对象.类型安全的,并且是安全的. 委托和接口的类似之处是:它们都允许分隔规范和实现. 一个原则: 被 ...
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- mfc实现c语言的注释,C语言学习:标识符、关键字、注释、表达式和语句
正文共:1526 字 2 图.预计阅读时间: 4 分钟. 文章由源世界原创,转载剽窃必究! 标识符 界说变量时,我们使用了诸如 a.abc.mn123 这样的名字,它们都是程序员自己起的,一般能够表达 ...
- UE4 C++:Delegate委托
目录 概念 定义 声明委托 单播委托 声明宏 绑定委托 执行函数 用法示例 不带参数Delegate 带参数Delegate 传递有效负载数据 多播委托 声明宏 绑定多播委托 多播执行 动态委托 声明 ...
- Java学习(静态static关键字,数组工具类Arrays,数学相关工具类(绝对值,向上取整,向下取整),继承,super和this关键字,抽象)
2022/1/2 (1/6)Java学习 1.静态Static关键字概述 一旦用了static关键字,那么这样的内容不再属于对象自己,而是属于类的,所以凡是本类的对象,都共享同一份. 2.静态stat ...
- Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论
Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...
最新文章
- python语言开发的软件有哪些-最适合人工智能开发的5种编程语言,你知道几种?...
- Spring第八发—自动装配及让Spring自动扫描和管理Bean
- 【Tools】Navicat Premium12安装教程
- python 日常小技巧
- linux内核支持的加密算法,Linux Kernel(Android) 加密算法总结(三)-应用程序调用内核加密算法接口...
- [Melodymood][流行经典]Take Me to your heart 《吻别》英文版
- 马云:将为每个非洲国家捐赠2万个检测试剂盒
- 精度、误差与分辨率的研究
- 怎样使用pyinstaller打包
- 人工智能在反洗钱领域的应用探索
- 打开shp文件最直接的思路
- 兜兜转转 - 2019开启CSDN博客的新篇章
- Spring Boot 错误页配置
- 这份 pip 使用方法,应该算是全网最全了
- java商城后台图片上传功能_淘淘商城图片上传功能的实现
- 基于android的ipcamera编程,spydroid-ipcamera-master完整实现源码
- 3D打印机喷头堵塞维修
- 老掉牙的ASP文件的加密与解密
- 《动手学深度学习》第二十三天---稠密连接网络(DenseNet)
- 电池pack结构_电池PACK是什么?锂电池包PACK结构设计需要考虑哪些因素?
热门文章
- IOS开发笔记3-C语言基础复习
- C语言函数集(二十一)
- 魅族android p,2.Android P新特性实践-Slices
- FragmentManager中Fragment的重复创建、复用问题
- IMAP IDLE模式(推送邮件)
- React:入门计数器
- 邪恶改装2:用单片机实现一次简单的wifi密码欺骗
- select的5中子句where,group by, havaing, order by, limit的使用顺序及实例
- SubclassWindow和SubclassDlgItem
- 未能创建Microsoft Visual C# 2008 编译器 解决方案【轉】