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与数据库开 ...
随机推荐
- jdbc 02: 连接mysql,并实现删除与更新
jdbc连接mysql,并实现删除与更新 package com.examples.jdbc.o2_删除与更新; import java.sql.*; //连接与插入 /* jdbc删除操作 */ p ...
- c++头文件的一个误导
通常情况下,我们都认为c++的头文件是这样的: #include <bits/stdc++.h> using namespace std; int main() 但c++也可以用c的头文件 ...
- 使用Python3.7+Tornado5.1配合七牛云存储api来异步切分上传文件
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_123 之前写了几篇关于FastDfs分布式存储的文章:python3.7.3操作FastDfs来进行文件操作,其实市面上关于云存储 ...
- error setting certificate verify locations
描述 在使用 git clone 克隆 GitHub 或者 Gitee 上的项目时,报如下错误: error setting certificate verify locations: CAfile: ...
- 项目导入 Vue Router 4 依赖包流程
下载 Vue Router 4 的依赖包: npm install vue-router@4 新建 router.ts 文件,导入 createRouter 以及 createWebHashHisto ...
- ipi发送阻塞导致crash
3.10的内核, 在子进程退出的时候,发送信号通知父进程,此时是持有父进程的sighand中的spinlock的,然后父进程和该子进程不在一个核上,发送ipi的reschedule中断给对应的核, 但 ...
- 从零开始实现一个MyBatis加解密插件
作者:vivo 互联网服务器团队- Li Gang 本篇文章介绍使用MyBatis插件来实现数据库字段加解密的过程. 一.需求背景 公司出于安全合规的考虑,需要对明文存储在数据库中的部分字段进行加密, ...
- Vue刷新页面VueX中数据清空了,怎么重新获取?
Vue刷新页面VueX数据清空了,怎么重新获取? 点击打开视频讲解更详细 在vue中刷新页面后,vuex中的数据就没有了,这时我们要想使用就要重新获取数据了, 怎么在刷新后重新获取数据呢??? 这时我 ...
- Spring的俩大核心概念:IOC、AOP
1.Spring 有两个核心部分: IOC 和 Aop (1)IOC:控制反转,把创建对象过程交给 Spring 进行管理 (2)Aop:面向切面,不修改源代码进行功能增强 2.Spring 特点 ...
- sftp服务器的搭建与连接
在个人租用的vps上搭建sftp服务器并通过本机连接上去 本实验所需:Xshell(xshell中包含xftp).一台vps(windows系统) sftp是一种协议,即SSH File Transf ...