一 什么是委托

可以认为委托是持有一个或多个方法的对象。可以执行委托,执行时委托会执行它所持有的方法。

从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 委托的更多相关文章

  1. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  2. C#基础篇 - 理解委托和事件

    1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...

  3. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  4. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  5. 9、委托、事件、Lambda

    开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.)   第 ...

  6. iOS 委托与文本输入(内容根据iOS编程编写)

    文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑  JXHypnosisViewController.m 修改  loadView 方法,向  ...

  7. C#委托异步调用

    参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...

  8. JavaScript事件代理和委托(Delegation)

    JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...

  9. .NET面试题系列[7] - 委托与事件

    委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...

  10. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

随机推荐

  1. day02-2

    JAVA入门 1.C&&C++ 1972年C诞生 贴近硬件,运行极快,效率极高 操作系统,编译器,数据库,网络系统等 指针和内存管理 1982年C++诞生 面向对象 兼容C 图形领域. ...

  2. mysql8.0二进制安装遇到的问题

    公司新项目需要用CentOS8.0以上的系统和mysql8.0:于是在虚拟机上开始操作测试: 一实验环境 1.系统版本:CentOS8.32.数据库版本:mysql-8.0.233.数据库下载链接:h ...

  3. Redis 5 种基本数据结构(String、List、Hash、Set、Sorted Set)详解 | JavaGuide

    首发于:Redis 5 种基本数据结构详解 - JavaGuide 相关文章:Redis常见面试题总结(上) . Redis 5 种基本数据结构(String.List.Hash.Set.Sorted ...

  4. 1269: 求最长上升子序列(LIS)

     题目描述: LIS问题(longest increasing subsequence),即:最长上升子序列问题,是动态规划中一个比较经典的问题.具体描述为:一个有n个整数的序列:A[1],A[2], ...

  5. python opencv图像识别(相同大小图片)

    简介 由于项目需要对比两张相同图片的相似度,因此采用opencv将图片转为灰阶数组,然后对比相应的数组来取相似度,此方法只适用于大小相同的图片,较为局限 # -*- coding: utf-8 -*- ...

  6. Fibonacci Nim

    目录 题意 题解 相关 Ref 题意 [COCI2010-2011#4] HRPA 取石子,但是: 先手第一次可取任意多个石子 此外每次可取的石子的个数,至少为 \(1\) ,至多为上一轮对方所取个数 ...

  7. SQL 字符串去除空格函数汇总

    SQL 中使用ltrim()去除左边空格 ,rtrim()去除右边空格 ,没有同时去除左右空格的函数,要去除所有空格可以用replace(字符串,' ',''),将字符串里的空格替换为空 . 例:去除 ...

  8. CodeTON Round 2 (Div. 1 + Div. 2, Rated, Prizes!) A-E

    比赛链接 A 题解 知识点:思维,模拟. 发现 \(b\) 串第一个字符是 \(1\) 则只能使用 max , \(0\) 则只能使用 min ,随后只需要模拟到 \(a\) 串剩余 \(m\) 个字 ...

  9. 用JavaScript写一个能开始和暂停的时钟

    //sScriptvar showTime = document.getElementById('seconds') var id =0 function fn(){ var i = 0 var s ...

  10. 金灿灿的季节 - Apache DolphinScheduler收获5位新Committer

    在这个金灿灿的收获季节,经过 Apache DolphinScheduler PPMC 们的推荐和投票,Apache DolphinScheduler 收获了 5 位新Committer .他们是:n ...