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

示例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. kafka以及消息队列详解

    Kafka 是LinkedIn 开发的一个高性能.分布式的消息系统. 用途:广泛用于日志收集.流式数据处理.在线和离线消息分发等场景. 1. Kafka 将消息流按Topic 组织,保存消息的服务器称 ...

  2. js验证手机号、身份证等

    //验证手机号function check_lxdh(lxdh){ var mobile = /^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0 ...

  3. matlab C程序

    通过把耗时长的函数用c语言实现,并编译成mex函数可以加快执行速度 Matlab本身是不带c语言的编译器的,所以要求你的机器上已经安装有VC,BC或Watcom C中的一种 注:在Matlab里,矩阵 ...

  4. [转]Oracle 11g R2 RAC高可用连接特性 – SCAN详解

    原文地址:http://czmmiao.iteye.com/blog/2124373   昨天帮朋友解决11g RAC SCAN问题,当时为这朋友简单解答了一些SCAN特性相关的问题,但我知道这仅仅是 ...

  5. 去掉没用的参数的warning

    #define UNUSED(x) ((void)(x)) void fun(int noused_arg, int b){ UNUSED(noused_arg); printf("%d\n ...

  6. python详解json模块

    我们在做工作中经常会使用到json模块,今天就简单介绍下json模块 什么是json JSON ,全称为JavaScript Object Notation, 也就是JavaScript 对象标记,它 ...

  7. 在C++工程上添加CUDA编译环境

    1.直接在新建工程的时候选择CUDA,这样的工程既能编译C++也能编译CU 2.在已有的C++工程上添加CUDA编译环境 右键工程-->生成依赖项-->生成自定义-->勾选CUDA ...

  8. 20.Java基础_对象的构造函数

    package pack1; public class Student { private String name; private int age; //构造方法 //如果没有任何构造函数,系统会自 ...

  9. 1.Python网络编程_UDP(简略版)

    # -*- coding: utf-8 -*- #2019-11-24 import socket def recv(): udp_socket=socket.socket(socket.AF_INE ...

  10. HTML与CSS学习笔记(5)

    1.文字阴影?(针对文字) text-shadow: 例如 text-shadow: 10px 10px 10px blue;四个值分别是 x y blur color blur表示模糊值,越大越模糊 ...