一. 泛型委托

  所谓的泛型委托,即自定义委托的参数可以用泛型约束,同时内置委托Func和Action本身就是泛型委托。

  将上一个章节中的Calculator类中的方法用自定义泛型委托重新实现一下。

  public class Calculator2
{
//传统解决方案一:在该类中声明多个方法,分别是加倍、平方、立方的方法 //传统解决方案二:在该类中声明一个万能方法,通过传递不同的参数类型来区分是执行加倍还是平方或者立方操作 //解决方案三:声明一个万能方法,传递一个委托进来,相当于传递了一个业务逻辑进行,在该方法里只需要执行即可
/// <summary>
/// 万能方法
/// </summary>
/// <param name="arrs">int类型的数组 </param>
/// <param name="mydel">自定义委托</param>
public delegate T myDel<T>(T t);
public static void MySpecMethord<T>(T[] arrs, myDel<T> myDel)
{
for (int i = ; i < arrs.Length; i++)
{
arrs[i] = myDel(arrs[i]);
//arrs[i] = mydel.Invoke(arrs[i]); //等价于上面那句
Console.WriteLine(arrs[i]);
}
} }

二. 内置委托

  .Net FrameWork提供两个支持泛型的内置委托,分别是Action和Func,结合lambda表达式,可以提高开发效率

  二者的区别:

  1.Action只能委托无返回值的方法,支持16个重载(in代表输入参数,该重载没有返回值)

  分别是:

    * public delegate void Action<in T>(T obj);

    * public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);

    * ......

    * public delegate void Action<in T1, in T2,......,in T16>(T1 arg1, T2 arg2,......,T16 arg16);

    *

  2.Func必须委托有返回值的方法,支持17个重载(注意括号里最后一个代表返回值,in代表输入参数,out代表返回值)

  分别是:

    * public delegate TResult Func<out TResult>();

    * public delegate TResult Func<in T, out TResult>(T arg);

    * public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

    * ......

    * public delegate TResult Func<in T1, in T2,.......in T16 out TResult>(T1 arg1, T2 arg2,......T16 arg16);

    *

  总结:除了ref参数和out参数,内置委托基本上能适用于任何泛型委托的场景,非常好用

    3. 内置委托和自定义委托的区别:

  自定义委托需要先声明一下,让系统认识这个自定义委托,然后才能实例化赋值方法;而内置委托系统本事就存在,所有不需要事先声明,直接实例化赋值方法即可

三. 委托的其它性质

  静态方法和实例方法对于委托的区别,对于静态方法,Target属性为null,所以效率比实例属性更高

  public class OtherCharacters
{
public delegate void mySpecDelegate();
/// <summary>
/// 1.测试普通实例方法和静态方法在委托中的区别
/// </summary>
public static void Test1()
{
MR mr=new MR();
//实例方法
mySpecDelegate a = mr.f1;
Console.WriteLine(a.Target==mr); //true
//静态方法
mySpecDelegate b = MR.f2;
Console.WriteLine(b.Target==null); //true
} } public class MR
{
/// <summary>
/// 普通方法
/// </summary>
public void f1()
{
}
//静态方法
public static void f2()
{ }
}

四. 事件

 1. 事件介绍

  * 定义:声明一个委托实例,然后在该实例的前面加上event关键字,就形成事件了

  * 事件的用途:实现广播和订阅的场景

  * 1.广播者:包括1个事件字段,独享执行委托的方法

  * 2.订阅者:通过调用 += 和 -= 来决定何时开始或停止订阅

  * 总结:事件是描述这种场景模式的一个词,事件是委托的一个子集,为了满足“广播/订阅”模式的需求而生

  * 事件和委托的区别:

  * 1. 委托是一种类型,而事件是委托的一个实例,然后在该实例前加上一个关键字

  * 2. 事件有一系列规则和约束用以保证程序的安全可控,事件只有 += 和 -= 操作,这样订阅者只能有订阅或取消订阅操作,没有权限执行其它操作

  * 3. 如果是委托,那么订阅者就可以使用 = 来对委托对象重新赋值(其它订阅者全部被取消订阅),甚至将其设置为null,甚至订阅者还可以直接调用委托,这些都是很危险的操作,广播者就失去了独享控制权

  * 4. 事件保证了程序的安全性和健壮性

 2. 下面代码就事件和委托进行比较

 public class MyEvent
{
//下面的案例用委托和事件实现相同的功能
public Action myDelegate;
/// <summary>
/// 触发委托执行的方法
/// </summary>
public void realizeDelegate()
{
if (myDelegate != null)
{
myDelegate.Invoke();
}
}
public event Action myEvent;
/// <summary>
/// 触发事件执行的方法
/// </summary>
public void realizeEvent()
{
if (myEvent != null)
{
myEvent.Invoke();
}
} #region 供委托和事件测试调用的方法 public static void T1()
{
Console.WriteLine("方法一");
} public static void T2()
{
Console.WriteLine("方法二");
} public static void T3()
{
Console.WriteLine("方法三");
} #endregion }

 3. 调用时候的区别:

 委托中的订阅者可以直接Invoke()来调用委托,而事件中的订阅者不能直接Invoke()调用委托,只能通过广播者中的方法来实现调用委托,从而保证广播者独享控制权。

  {
Console.WriteLine("--------------------------七. 事件------------------------------------");
MyEvent m1 = new MyEvent();
//1. 委托实现
Console.WriteLine("--------------------------1. 委托实现------------------------------------");
//订阅者进行订阅
m1.myDelegate += MyEvent.T1;
m1.myDelegate += MyEvent.T2;
m1.myDelegate += MyEvent.T3;
m1.myDelegate.Invoke(); //委托中的订阅者可以直接调用委托
m1.myDelegate -= MyEvent.T2;
m1.realizeDelegate();
//2. 事件实现
Console.WriteLine("--------------------------2. 事件实现------------------------------------");
m1.myEvent += MyEvent.T1;
m1.myEvent += MyEvent.T2;
m1.myEvent += MyEvent.T3;
// m1.myEvent.Invoke(); //事件中的订阅者不能直接调用委托
m1.realizeEvent(); //只能通过发布者中方法来实现委托,保证发布者独享控制权
m1.myEvent -= MyEvent.T2;
m1.realizeEvent(); }

  结果:

第十节:委托和事件(2)(泛型委托、Func和Action、事件及与委托的比较)的更多相关文章

  1. 第一百二十节,JavaScript事件对象

    JavaScript事件对象 学习要点: 1.事件对象 2.鼠标事件 3.键盘事件 4.W3C与IE JavaScript事件的一个重要方面是它们拥有一些相对一致的特点,可以给你的开发提供更多的强大功 ...

  2. C# 关于委托和事件的妙文:通过一个例子详细介绍委托和事件的作用;Observer模式简介

    委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见 ...

  3. 按自己的想法去理解事件和泛型(C#)

    上一篇那些年困扰我们的委托(C#)讲了委托,这一篇自然就轮到事件了. 不喜欢官方的表达方式,喜欢按照自己的想法去理解一些抽象的东西. 事件 考虑到委托使用的一些缺陷,就有了事件.委托是不安全的,打个比 ...

  4. 第三百五十节,Python分布式爬虫打造搜索引擎Scrapy精讲—selenium模块是一个python操作浏览器软件的一个模块,可以实现js动态网页请求

    第三百五十节,Python分布式爬虫打造搜索引擎Scrapy精讲—selenium模块是一个python操作浏览器软件的一个模块,可以实现js动态网页请求 selenium模块 selenium模块为 ...

  5. centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课

    centos    LAMP第二部分apache配置  下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转  配置apache的访问日志  配置静态文件缓存  配置防盗链 ...

  6. centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobackupex/Xtrabackup 第四十节课

    centos   shell编程6一些工作中实践脚本   nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志  直接送给bc做计算  gzip  innobacku ...

  7. C#编程语言之委托与事件(一)—— C/C++函数指针和C#委托初步

    相信正在学习C#的人都有学习过C或C++的经验,本文要讲的第一个要点是C#中的委托(delegate,有些资料也叫代表).什么是委托,很多人都能自然而然地想到C/C++中的函数指针,事实上很多书和资料 ...

  8. 第十节:详细讲解一下Java多线程,随机文件

    前言 大家好,给大家带来第十节:详细讲解一下Java多线程,随机文件的概述,希望你们喜欢 多线程的概念 线程的生命周期 多线程程序的设计 多线程的概念 多线程的概念:程序是静态的,进程是动态的.多进程 ...

  9. 第三百八十节,Django+Xadmin打造上线标准的在线教育平台—将所有app下的models数据库表注册到xadmin后台管理

    第三百八十节,Django+Xadmin打造上线标准的在线教育平台—将所有app下的models数据库表注册到xadmin后台管理 将一个app下的models数据库表注册到xadmin后台管理 重点 ...

随机推荐

  1. Docker(2):使用Dockerfile创建支持SSH服务的镜像

    1.创建工作目录 # mkdir sshd_ubuntu # ls 在其中,创建Dockerfile和run.sh文件 # cd sshd_ubuntu/ # touch Dockerfile run ...

  2. SQL CREATE TABLE 语句

    CREATE TABLE 语句 CREATE TABLE 语句用于创建数据库中的表. SQL CREATE TABLE 语法 CREATE TABLE 表名称 ( 列名称1 数据类型, 列名称2 数据 ...

  3. sub2ind函数

    sub2ind函数是MATLAB中对矩阵索引号检索的函数,用法如下: >> A=rand(5) A = 0.6850    0.0867    0.2290    0.1006    0. ...

  4. Sublime 禁止自动升级

    打开SUblime   Prefreences  找到"设置-用户" 添加 "update_check":false, 即可禁用默认升级 此时完整如下 { &q ...

  5. 分享:大型Web网站架构演变之9大阶段

    前言 我们以Java Web为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变. 该系统具备的功能: 用户模块:用户注册和管理 商品模块:商品展示和管理 交易模块:创建交易和管理 正文 阶 ...

  6. 论PHP框架设计模式及MVC的缺陷

    目前主流的PHP框架设计模式均为MVC模式,比如yii或codeigniter,均是由控制器接收页面请求,并沟通模型与视图的交互.如果我们把网站整体看作一个矩阵,把网站接收用户请求并处理看作是网站的竖 ...

  7. Maven将远程包拉去到项目指定路径

    <build> <plugins> <plugin> <artifactId>maven-dependency-plugin</artifactI ...

  8. mysql-笔记--增删改查

    查看数据库:可以使用 show databases; 命令查看已经创建了哪些数据库 指定数据库:在登录后使用 use 语句指定, 命令: use 数据库名;要对一个数据库进行操作, 必须先选择该数据库 ...

  9. Python学习之路——函数对象作用域名称空间

    一.函数对象 # 函数名就是存放了函数的内存地址,存放了内存地址的变量都是对象,即 函数名 就是 函数对象 # 函数对象的应用 # 1 可以直接被引用 fn = cp_fn # 2 可以当作函数参数传 ...

  10. [Linux] Vim 撤销 回退 操作

    在vi中按u可以撤销一次操作 u   撤销上一步的操作      Ctrl+r 恢复上一步被撤销的操作 注意:        如果你输入“u”两次,你的文本恢复原样,那应该是你的Vim被配置在Vi兼容 ...