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

示例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. Python切片中的误区与高级用法

    众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串.列表.元组...)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢? 切片(slice)就是一种截取索引片段的技术,借助切片 ...

  2. new一个对象的初始化过程

    ############################### 今天总结一下,new对象的初始化过程. ############################### 首先,当不含static成员时, ...

  3. .NET Core下自带容器IServiceCollection以及AutoFac以及AutoFac中AOP简介

    https://www.cnblogs.com/artech/p/net-core-di-01.html 大内老A的在.NET Core下对这些的介绍,有一系列文章 https://www.cnblo ...

  4. 微信小程序和支付宝小程序富文本使用

    微信小程序使用的是 1. wxml 页面元素的最简单使用 <rich-text nodes="{{这是你的数据}}"></rich-text>   2. j ...

  5. 新手教程丨利用Python制作一款截图识别软件!

    进入正文前给大家推荐一个微软开发的工具:Snipaste. 这是一款截图软件,把截出的图片放置到窗口上,可以随意移动,使用非常方便,并且支持各类电脑系统. 先简单介绍一下它的用法,F1截图,Ctrl+ ...

  6. 当cell中有UItextfiled或者UITextVIew时,弹出键盘把tableview往上,但是有的cell没有移动

    cell中有UITextView时,输入文字是需要将tableView向上移,基本的做法是,注册键盘变化的通知在通知的方法中做tableVIew的位置调整, 一,一般做法 - (void)regist ...

  7. Toast实现源码解析

    说明 本篇文章用于介绍Android中Toast的实现原理.和简单实现一个自定义的Toast. Toast实现 一般常用Toast格式为: Toast.makeText(context,"t ...

  8. mssql 单引号插入到sqlserver的方法分享

    转自:http://www.maomao365.com/?p=6740 摘要: 下文讲述sqlserver操作中遇到单引号的处理方法sqlserver 数据库中可以存储任何字符,因为在数据库中字符都是 ...

  9. Django框架(二十二)-- Django rest_framework-解析器

    一.解析器的作用 根据请求头 content-type 选择对应的解析器对请求体内容进行处理,将传过来的数据解析成字典 二.使用解析器 1.局部使用 在视图类中重定义parser_classes即可, ...

  10. [Go] 并发imap收信

    并发数太大会直接死,这里有时候需要多试几次 package main import ( "flag" "fmt" "io/ioutil" & ...