上一篇文章写了委托的最基本的一些东西,本篇咱们扯扯委托其他的东西。

示例1插件编程

根据对委托的理解,委托可以把一个方法当作参数进行传递,利用这个特性我们可以使用委托,实现插件编程。

public delegate int Transformer(int x);

class Util{
pubilc static void Transform(int[] values, Transformer t){
for(int i = 0; i < values.Length; i++){
values[i] = t?.Invke(values[i]);
}
}
} class Test{
static void Main(){
int[] values = {1,2,3};
Util.Transform(values, Sqare); foreach(int i in values){
Console.WriteLine(i + " "); //1 4 9
}
} static int Sqare (int x) => x * x;
}

这里的Transform方法就是插件方法,它接受一个委托参数。

示例2多播委托

所有的委托都有多播的能力。这就意味着一个委托可以引用一个方法,或者引用一个组方法。委托使用 += 和 -=运算符联结多个委托实例。

public class People{}
public class Student:People{}
public delegate void Action(); class Program
{
static void Say(){
Console.WriteLine("Say HI");
}
static void Write(){
Console.WriteLine("Write Anything");
} Action action = Say;
action += Write;//action = action + Write;
action(); /*
Say HI
Write Anything
*/ }

委托会按照添加的顺序依次触发。如果存在返回值,那么调用者会将最后一个带有非void返回值类型的方法返回值进行返回,其他的返回值将会抛弃。

- 和-= 运算符会从左侧委托操作数中将右侧的委托操作删除。

对于为值为null的委托执行 + 或者+= 操作,等价于为委托指定一个新的值。同样在当委托只有一个目标方法时,执行-=操作等价于为委托指定null值。

由于委托是一个类,所以委托是不可变,每次执行 += 或者-= 实质上等价于从新创建一个新的委托实例,并为它赋值。

具体使用,比如说我们要建一栋大楼,需要很长一段时间,但是公司有要求每建好一层需要给公司汇报一下。

public delegate void ProgressReporter(int floor);

public class Edifice{
public static void Build(ProgressReporter p){
for(int i = 0; i < 18; i++){
p(i); System.Threading.Thread.Sleep(1000);//添加点时间
}
}
}
class Test{
static void Main(){
ProgressReporter p = WriteProgressToConsole;
p += AdviseToCompany;
Edifice.Build(p);
} static void WriteProgressToConsole(int fool) => Console.WriteLine($"{fool}层已建成"); static void AdviseToCompany(int fool) => Console.WriteLine($"**项目,已经建好{fool}层。"); }

示例3泛型委托

委托类型可以包含泛型类型参数,如:

public delegate T Transformer<T> (T t);

通过一个泛型参数,我们可以定义一个通用的Transformer,让它对任何类型都有效:

public class util{
public static void Transform<T> (T[] values, Transformer<T> t){
for(int i = 0; i < values.Length; i++){
values[i] = t(values[i]);
}
}
}
class Test{
static void Main(){
int[] values = {1,2,3};
Util.Transformer(values, Square); foreach(int i in values){
Console.Write(i + " "); //1 4 9
}
} static int Sqare (int x) => x * x; }

既然委托支持泛型参数,那么就可以定义一些小型的委托类型,它们可以具有任意的返回类型和合理的数目的参数,类如系统定义好的Action委托和Func委托(out和in标记可变性修饰符,在逆变和协变中有解释)。

delegate void Action();
delegate void Action<in T> (T arg);
delegate void Action<in T1, in T2> (T1 arg1, T2 arg2)
………
delegate TResule Func(out TResule)();
delegate TResule Func<in T, out TResule> (T arg);
delegate TResule Func<in T1, in T2, out TResule> (T1 arg1, T2 arg2)
………

其中Action和Func 都可以支持16个参数。

上面的Transform重写.

public static void Transform<T> (T[] values, Func<T, T> transformer){
for(int i = 0; i < values.Length; i++){
values[i] = transformer(values[i]);
}
}

委托还有很多东西,下次聊!

参考自C#7.0核心技术指南

C# 委托补充01的更多相关文章

  1. Python补充01 序列的方法

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在快速教程中,我们了解了最基本的序列(sequence).回忆一下,序列包含有定值 ...

  2. 【Python 补充01】Python运算符

    Python运算符 举个简单的例子 4 +5 = 9 . 例子中,4 和 5 被称为操作数,"+" 称为运算符. 1.算术运算符 + - * / # 加减乘除 % # 取模(返回除 ...

  3. 第三课补充01——set类型 sorted类型命令操作详解,redis管道及事务

    1. set类型的命令操作: (1)sadd命令:向key指定的set集合添加成员 ##sadd命令:是设置set集合类型的数据,sadd  <key> <mumber> [& ...

  4. 第二课补充01——redis-cli命令行详解、string类型、list类型、hash类型命令操作详解

    一. redis-cli命令行参数 1.-x参数:从标准输入读取一个参数: [问题] [解决] 因为echo命令是默认带有回车\n的,不带回车需要echo –n命令: echo -n "ha ...

  5. 补充01 Django 类视图

    视图 函数视图[Function Base View] 以函数的方式定义的视图称为函数视图,函数视图便于理解.但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不 ...

  6. python教程与资料

    网上有个人写的python快速教程,非常好.比看书好多了.猛击下面的链接地址 http://www.douban.com/group/topic/30008503/ python文档资料收集 pyth ...

  7. 【Python大系】Python快速教程

    感谢原作者:Vamei 出处:http://www.cnblogs.com/vamei 怎么能快速地掌握Python?这是和朋友闲聊时谈起的问题. Python包含的内容很多,加上各种标准库.拓展库, ...

  8. Python快速教程目录(转)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 怎么能快速地掌握Python?这是和朋友闲聊时谈起的问题. Python包含的内容 ...

  9. java实现smtp邮件发送

    一.准备工作 首先你需要已一个发送邮箱,一般的邮箱都有SMTP.POP3服务,比如QQ邮箱,登陆QQ邮箱开启SMTP服务,开启是服务器会提示你设置独立密码,这个密码是跟邮箱正常登陆的密码不同的,这个是 ...

随机推荐

  1. C#反射调用类的私有方法

    void Main() { var type = typeof(StockClass); type.Dump(); var fields=type.GetFields(BindingFlags.Ins ...

  2. IIS安装和ASP.NET Web应用程序开发期间部署到IIS自定义主机域名并附加进程调试

    一.IIS安装,此处以Windows10操作系统为例 首先依次进入控制面板=>程序=>程序与功能=>启用或关闭Windows功能 将Internet开头的三个选项全部打钩后点击确定安 ...

  3. Python线程与进程 I/O多路复用

    SSHClient Paramiko模块 远程执行命令 #用户名密码方式: import paramiko ssh = paramiko.SSHClient() ssh.set_missing_hos ...

  4. PHP中设计模式以及魔术方法

    1.设计模式        1.1单例模式        口诀:三私一公 1.私有的静态属性用来保存对象的单例 2.私有的构造方法用来阻止在类的外部实例化 3.私有的__clone阻止在类的外部clo ...

  5. Java生鲜电商平台-订单中心服务架构与异常订单逻辑

    Java生鲜电商平台-订单中心服务架构与异常订单逻辑 订单架构实战中阐述了订单系统的重要性,并从订单系统的信息架构和流程上对订单系统有了总体认知,同时还穿插着一些常见的订单业务规则和逻辑.上文写到订单 ...

  6. JS基础语法---continue关键字

    continue: 在循环中如果遇到continue关键字,直接开始下一次循环 如下:continue在计数器之前,会一直循环,浏览器会崩溃,我的就崩溃了 var i = 0; while (i &l ...

  7. sftp-server 搭建编译

    下载开源代码 https://github.com/zwx230741/openssh-portable 编译 # autoconf # ./configure --prefix=xxx # make ...

  8. ABP进阶教程2 - 组合查询

    点这里进入ABP进阶教程目录 更新数据传输对象 打开应用层(即JD.CRS.Application)的Course\Dto\GetAllCoursesInput.cs //Course数据传输对象(查 ...

  9. C# 第三方库

    基本上选用的都是 https://www.nuget.org 分类中最流行的那个库 1. 日志工具库 NLOG Stackify.com 简单入门文章  https://stackify.com/nl ...

  10. TICK技术栈(一)TICK技术栈介绍

    1.什么是TICK技术栈? 1.1 简介 TICK 是由 InfluxData开发的一套开源工具栈,由 Telegraf, InfluxDB, Chronograf, Kapacitor 四个工具的首 ...