C#-9 委托
一 什么是委托
可以认为委托是持有一个或多个方法的对象。可以执行委托,执行时委托会执行它所持有的方法。
从C++的角度理解,委托可以看成一个类型安全、面向对象的C++函数指针。
delegate void MyDel(int value); //声明委托类型
class Program
{
void PrintLow(int value)
{
Console.WriteLine($"Low value is {value}");
}
void PrintHigh(int value)
{
Console.WriteLine($"High value is {value}");
}
static void Main(string[] args)
{
var program = new Program(); MyDel myDel; //声明一个Mydel委托类型的变量myDel;
var random = new Random().Next(99); if (random < 50)
{
myDel = new MyDel(program.PrintLow); //创建一个包含PrintLow的委托对象将其赋值给myDel变量;
}
else
{
myDel = new MyDel(program.PrintHigh);
} myDel(random); //执行委托
}
}
二 委托概述
委托和类一样,是一种用户自定义的类型。
可以把委托看作一个包含有序方法列表的对象,这些方法具有相同的签名和返回类型。
- 方法的列表称为调用列表;
- 委托持有的方法可以来自任何类或结构,只有方法的返回类型和签名是匹配的;
- 调用列表中的方法可以是实例方法也可以是静态方法;
- 在调用委托时,会执行其列表中的所有方法。
三 声明委托类型
delegate void MyDel(int value); //声明委托类型
声明委托类型以delegate关键字开头,指定了MyDel类型的委托只会接受无返回值并且有单个int参数的方法。
四 创建委托对象
委托是引用类型,因此有引用和对象。在委托类型声明之后,我们可以声明变量并创建委托类型的对象。
有两种创建委托对象的方式。
delegate void MyDel(int value); //声明委托类型
class MyInstClass
{
public void MyM1(int value)
{
Console.WriteLine($"MyM1:{value}");
}
}
class SClass
{
public static void OtherM2(int value)
{
Console.WriteLine($"OthreM2{value}");
}
}
class Program
{
static void Main(string[] args)
{
var myInstObj = new MyInstClass();
// 1. 带new运算符的对象创建
var delVar = new MyDel(myInstObj.MyM1);
var dVar = new MyDel(SClass.OtherM2);
// 2. 快捷语法
MyDel delVar1 = myInstObj.MyM1;
MyDel dVar1 = SClass.OtherM2; // 给委托变量赋值会改变包含在委托变量中的引用
delVar = SClass.OtherM2;
}
}
五 组合委托
以下代码创建了两个委托,第三个委托有前两个委托组合而成。
MyDel delA = myInstObj.MyM1;
MyDel delB = SClass.OtherM2;
MyDel delC = delA + delB; //组合调用列表
六 为委托添加方法
委托其实是不变的,不过C#提供了看上去可以为委托添加方法的语法,使用+=运算符;
var inst = new MyInstClass();
MyDel delVar = inst.MyM1; //创建委托
delVar += SCL.M3; //增加方法
delVar += X.ACT; //增加方法
在使用+=运算符时,实际发生的是创建了一个新的委托,其调用列表是左边的委托加上右边方法的组合,然后将这个新的委托赋值给delVar。
七 为委托移除方法
使用 -=运算符为委托移除方法。
delVar -= SCL.M3; //从委托移除方法
与委托增加方法一样,其实是创建了一个新的委托;
如果调用列表中的方法有多个实例,-=运算符将从列表最后开始搜索,并且移除第一个与方法匹配的实例;
试图删除委托中不存在方法没有效果;
试图调用空委托会抛出异常。
八 调用委托
可以像调用方法一样简单地调用委托。用于调用委托的参数将会用于调用列表中的每一个方法。
var inst = new MyInstClass();
MyDel delVar = inst.MyM1; //创建委托
delVar += SCL.M3; //增加方法
delVar += X.ACT; //增加方法
delVar(55); //调用委托
九 调用带返回值的委托
如果委托有返回值并且其调用列表中有一个以上的方法:
- 调用列表中最后一个方法的返回值就是委托调用返回的值;
- 调用列表中其他方法的返回值会被忽略。
十 调用带引用参数的委托
如果委托有引用参数,参数值会根据调用列表中的一个或多个方法的返回值而改变。
delegate void MyDelegate(ref int x);
class Program
{
public static void Add2(ref int x) { x += 2; }
public static void Add3(ref int x) { x += 3; } static void Main(string[] args)
{
MyDelegate myDel = Program.Add2;
myDel += Program.Add3;
int x = 5;
myDel(ref x);
Console.WriteLine(x);
Console.Read();
}
}
输出:10
十一 匿名方法
匿名方法是在初始化委托时内联声明的方法。
delegate int MyDelegate(int x);
class Program
{
static void Main(string[] args)
{
//使用匿名方法
MyDelegate myDel = delegate (int x)
{
return x + 20;
};
//委托的返回类型是int,则匿名方法中的代码也必须返回int类型的值。
}
}
可以在如下地方使用匿名方法:
- 声明委托变量时作为初始化表达式;
- 组合委托时在赋值语句的右边;
- 为委托增加事件时在赋值语句的右边。
匿名方法表达式的语法包含:
- delegate关键字;
- 参数列表,如果没有参数则可以省略;
- 语句块,包含了匿名方法的代码。
匿名方法不会显示声明返回值,而其中的代码行为必须通过返回一个在类型上与委托的返回类型相同的值来匹配委托的返回类型。
如果委托有void类型的返回值,匿名方法就不能返回值。
十二 Lambda表达式
C#3.0引入了Lambda表达式,简化了匿名方法的语法,直接描述方法的定义。
delegate int MyDelegate(int x);
class Program
{
static void Main(string[] args)
{
MyDelegate myDel = delegate (int x) { return x + 1; }; //匿名方法
MyDelegate myDel1 = (int x) => { return x = 1; }; //Lanbda表达式
MyDelegate myDel2 = (x) => { return x = 1; }; //Lanbda表达式
MyDelegate myDel3 = x => { return x = 1; }; //Lanbda表达式
MyDelegate myDel4 = x => x = 1; ; //Lanbda表达式
}
}
C#-9 委托的更多相关文章
- HTML 事件(三) 事件流与事件委托
本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...
- C#基础篇 - 理解委托和事件
1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...
- [.NET] C# 知识回顾 - 委托 delegate (续)
C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...
- [C#] C# 知识回顾 - 委托 delegate
C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...
- 9、委托、事件、Lambda
开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.) 第 ...
- iOS 委托与文本输入(内容根据iOS编程编写)
文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑 JXHypnosisViewController.m 修改 loadView 方法,向 ...
- C#委托异步调用
参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...
- JavaScript事件代理和委托(Delegation)
JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...
- .NET面试题系列[7] - 委托与事件
委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...
- .NET基础拾遗(4)委托、事件、反射与特性
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
随机推荐
- scala WordCount案例
数据样例: java,spark,hadoop,python,datax java,spark,hadoop,spark,python,datax java,spark,hadoop,python,d ...
- vue发布自定义组件到npm
一.使用 vue create currentdatetime创建项目(可查考https://cli.vuejs.org/zh/guide/creating-a-project.html),创建成功后 ...
- angular变化检测OnPush策略需要注意的几个问题
OnPush组件内部触发的事件(包括viewChild)会引起组件的一次markForCheck Detached组件内部触发的事件不会引起组件的变化检测 OnPush组件的contentChild依 ...
- JAVA定时任务原理入门
本文适用语言:java 序章:定时任务实现方式 当下,java编码过程中,实现定时任务的方式主要以以下两种为主 spring框架的@Scheduled quzrtz框架 网络上关于这两种框架的实践和配 ...
- CMake库搜索函数居然不搜索LD_LIBRARY_PATH
摘要: 本文通过编译后运行找不到库文件的问题引入,首先分析了find_package(JNI)的工作流程,而后针对cmake不搜索LD_LIBRARY_PATH的问题,提出了一种通用的解决办法. 本文 ...
- MySQL sql优化(摘抄自文档)
前言 有人反馈之前几篇文章过于理论缺少实际操作细节,这篇文章就多一些可操作性的内容吧. 注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础. 优化目标 ...
- Odoo14 TypeError: Cannot read property 'classList' of undefined
Traceback: TypeError: Cannot read property 'classList' of undefined at Class.setLocalState (http://l ...
- PyTorch中的CUDA操作
CUDA(Compute Unified Device Architecture)是NVIDIA推出的异构计算平台,PyTorch中有专门的模块torch.cuda来设置和运行CUDA相关操作.本 ...
- elasticsearch设置密码及Java密码连接
目录 1. 安装 2. 修改elasticsearch-8.2.2\config\elasticsearch.yml文件里面xpack.security.enabled: false为 3. 重新启动 ...
- Docker_删除none镜像
Docker 删除 none 镜像 docker images|grep none|awk '{print $3}'|xargs docker rmi