第十节:委托和事件(2)(泛型委托、Func和Action、事件及与委托的比较)

一. 泛型委托

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

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

复制代码

 1  public class Calculator22     {3         //传统解决方案一:在该类中声明多个方法,分别是加倍、平方、立方的方法4 5 6         //传统解决方案二:在该类中声明一个万能方法,通过传递不同的参数类型来区分是执行加倍还是平方或者立方操作7 8 9         //解决方案三:声明一个万能方法,传递一个委托进来,相当于传递了一个业务逻辑进行,在该方法里只需要执行即可
10         /// <summary>
11         /// 万能方法
12         /// </summary>
13         /// <param name="arrs">int类型的数组 </param>
14         /// <param name="mydel">自定义委托</param>
15         public delegate T myDel<T>(T t);
16         public static void MySpecMethord<T>(T[] arrs, myDel<T> myDel)
17         {
18             for (int i = 0; i < arrs.Length; i++)
19             {
20                 arrs[i] = myDel(arrs[i]);
21                 //arrs[i] = mydel.Invoke(arrs[i]);  //等价于上面那句
22                 Console.WriteLine(arrs[i]);
23             }
24         }
25 
26     }

复制代码

二. 内置委托

  .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,所以效率比实例属性更高

复制代码

 1  public class OtherCharacters2     {3         public delegate void mySpecDelegate();4         /// <summary>5         /// 1.测试普通实例方法和静态方法在委托中的区别6         /// </summary>7         public static void Test1()8         {9             MR  mr=new MR();
10             //实例方法
11             mySpecDelegate a = mr.f1;
12             Console.WriteLine(a.Target==mr);   //true
13             //静态方法
14             mySpecDelegate b = MR.f2;
15             Console.WriteLine(b.Target==null);  //true
16         }
17 
18     }
19 
20     public class MR
21     {
22         /// <summary>
23         /// 普通方法
24         /// </summary>
25         public void f1()
26         {
27         }
28         //静态方法
29         public static void f2()
30         {
31 
32         }
33     }

复制代码

四. 事件

 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()调用委托,只能通过广播者中的方法来实现调用委托,从而保证广播者独享控制权。

复制代码

 1  {2                 Console.WriteLine("--------------------------七. 事件------------------------------------");3                 MyEvent m1 = new MyEvent();4                 //1. 委托实现5                 Console.WriteLine("--------------------------1. 委托实现------------------------------------");6                 //订阅者进行订阅7                 m1.myDelegate += MyEvent.T1;8                 m1.myDelegate += MyEvent.T2;9                 m1.myDelegate += MyEvent.T3;
10                 m1.myDelegate.Invoke();  //委托中的订阅者可以直接调用委托
11                 m1.myDelegate -= MyEvent.T2;
12                 m1.realizeDelegate();
13                 //2. 事件实现
14                 Console.WriteLine("--------------------------2. 事件实现------------------------------------");
15                 m1.myEvent += MyEvent.T1;
16                 m1.myEvent += MyEvent.T2;
17                 m1.myEvent += MyEvent.T3;
18                 // m1.myEvent.Invoke();    //事件中的订阅者不能直接调用委托
19                 m1.realizeEvent();         //只能通过发布者中方法来实现委托,保证发布者独享控制权
20                 m1.myEvent -= MyEvent.T2;
21                 m1.realizeEvent();  
22 
23             } 

复制代码

  结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438584.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java+sm4+加密算法_SM4加密算法实现Java和C#相互加密解密

https://www.cnblogs.com/miaoziblog/p/9040473.html近期由于项目需要使用SM4对数据进行加密&#xff0c;然后传给Java后台&#xff0c;Java后台使用的也是SM4的加密算法但是就是解密不正确&#xff0c;经过一步步调试发现Java中好多数据类型与C#的相同的数据类型是存在不同的比…

DotNet进阶系列

一. 回顾历史 回顾个人发展历程&#xff0c;自2012年初次接触开发至今(2018年)已经有六个年头&#xff0c;这期间陆陆续续学习并掌握了不少技术&#xff0c;C#语言、ORM框架、多线程技术、设计模式、前端技术、MVC、MVVM框架思想等等&#xff0c;每种技术随着多次使用&#xff…

第十一节:特性(常见的特性标签、自定义特性、特性的使用案例)

一. 基本概念 1. 什么是特性? MSDN官方给出的定义时&#xff1a;公共语言运行时允许添加类似关键字的描述声明&#xff0c;叫做特性&#xff0c;它对程序中的元素进行标注&#xff0c;如类型、字段、方法和属性等。Attribute和Microsoft .Net Framework文件的元数据&#xff…

第十二节:Lambda、linq、SQL的相爱相杀(1)

一. 谈情怀 Lambda、Linq、SQL伴随着我的开发一年又一年&#xff0c;但它们三者并没有此消彼长&#xff0c;各自占有这一定的比重&#xff0c;起着不可替代的作用。 相信我们最先接触的应该就是SQL了&#xff0c;凡是科班出身的人&#xff0c;大学期间都会学习SQL Server数据库…

php java 共享session_PHP 实现多服务器共享 SESSION 数据

一、问题起源稍大一些的网站&#xff0c;通常都会有好几个服务器&#xff0c;每个服务器运行着不同功能的模块&#xff0c;使用不同的二级域名&#xff0c;而一个整体性强的网站&#xff0c;用户系统是统一的&#xff0c;即一套用户名、密码在整个网站的各个模块中都是可以登录…

第十三节:Lambda、linq、SQL的相爱相杀(2)

一. Linq开篇 1.Where用法 linq中where的用法与SQL中where的用法基本一致。 1 #region 01-where用法2 {3 //1. where用法4 //1.1 查询账号为admin的用户信息5 Console.WriteLine("------------…

第十四节:Lambda、linq、SQL的相爱相杀(3)

一. SQL 开篇 1. where用法 1    #region 封装EF调用SQL语句查询 2 public static List<T> ExecuteQuery<T>(string sql, params SqlParameter[] pars) 3 { 4 return db.Database.SqlQuery<T>(sql, pars).ToList(); 5 …

第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)

一. 基本介绍 回忆&#xff1a; 最早接触到表达式目录树(Expression)可能要追溯到几年前使用EF早期的时候&#xff0c;发现where方法里的参数是Expression<Func<T,bool>>这么一个类型&#xff0c;当初不是很理解&#xff0c;只是知道传入lambda表达式使用即可&…

IIS Web 服务器/ASP.NET 运行原理基本知识概念整理

前言&#xff1a; 记录 IIS 相关的笔记还是从公司笔试考核题开始的&#xff0c;问 Application Pool 与 AppDomain 的区别&#xff1f; 促使我对进程池进了知识的学习&#xff0c;所以记录一下学习的笔记。 我们知道现在 .NET 就业来看&#xff0c;80% 的 .NET 程序员都是从事 …

Http请求处理流程

从一个页面比如www.xuxiaoyu.net的请求开始如何就能打开blogs页面的呢&#xff1f;这其中发生了什么样的东西&#xff1f; Http请求(Http Request) 当服务器&#xff08;IIS&#xff09;接受到一个Http请求的时候进行以下步骤的处理&#xff1a; 1)服务器获取所请求的页面的后缀…

iis到w3wp的数据流及工作原理

HTTP.sys->IO线程-CLR线程池中的worker线程处理 IO线程只负责把请求交给Worker线程或者放入进程池级别的队列,然后又去HTTP.SYS的队列中处理其它的请求

php云解析播放器,xyplay云解析PHPV3.4.1优化稳定版视频解析

演示地址&#xff1a;如有演示站请以演示为准&#xff0c;无演示站以截图为准,源码太多服务器有限&#xff0c;无法搭建所有源码演示站&#xff0c;请谅解&#xff01;新手购买指导&#xff1a;1.在本站注册账号 丨 2.登录已注册账号充值源码所需金币 丨 3.登录账号下载所需源码…

php version.,PHP_VERSION指什么

PHP_VERSION (string)当前的PHP版本&#xff0c;以字符串形式“ major.minor.release [extra]”表示。 (推荐学习&#xff1a;PHP视频教程)例如&#xff1a;<?php // PHP_VERSION_ID 自 PHP 5.2.7 起有效&#xff0c;// 如果我们的版本低于该版本&#xff0c;则用以下代码来…

C# async 和 await 理解

先假设如下场景&#xff1a; 主函数 Main&#xff0c;循环等待用户输入&#xff1b; 计算函数 Cal&#xff0c;耗时计算大量数据&#xff1b; class Test {static int Main(string[] args){while(true){// 等待用户输入}}public static int Cal() {int sum 0;for (int i …

C# 彻底搞懂async/await

前言 Talk is cheap, Show you the code first&#xff01; private void button1_Click(object sender, EventArgs e) {Console.WriteLine("111 balabala. My Thread ID is :" Thread.CurrentThread.ManagedThreadId);AsyncMethod();Console.WriteLine("222 …

c#之task与thread区别及其使用

1.什么是thread 当我们提及多线程的时候会想到thread和threadpool&#xff0c;这都是异步操作&#xff0c;threadpool其实就是thread的集合&#xff0c;具有很多优势&#xff0c;不过在任务多的时候全局队列会存在竞争而消耗资源。thread默认为前台线程&#xff0c;主程序必须等…

java内存分配和垃圾回收,Java内存分配与垃圾回收

1.JVM管理的内存包含下图所示的几个运行时数据区域&#xff0c;其中方法区和堆为线程共享的数据区域&#xff0c;程序计数器&#xff0c;虚拟机栈以及本地方法栈为线程私有的数据区域。程序计数器&#xff1a;可以看做是当前线程所执行的字节码的行号指示器&#xff0c;告诉字节…

谈谈你对闭包的理解?

闭包这个概念好难理解&#xff0c;身边朋友们好多都稀里糊涂的&#xff0c;稀里糊涂的林老冷希望写下这篇文章能够对稀里糊涂的伙伴们有一些帮助~ 请大家跟我理解一下&#xff0c;如果在一个函数的内部定义了另一个函数&#xff0c;外部的我们叫他外函数&#xff0c;内部的我们…

php有哪些开源社区,PHP开源社区

简介Blade 是 Laravel 提供的一个简单而又强大的模板引擎。和其他流行的 PHP 模板引擎不同&#xff0c;Blade 并不限制你在视图中使用原生 PHP 代码。所有 Blade 视图文件都将被编译成原生的 PHP 代码并缓存起来&#xff0c;除非它被修改&#xff0c;否则不会重新编译&#xff…

GetType和typeof的区别

typeof: The typeof operator is used to obtain the System.Type object for a type. 运算符&#xff0c;获得某一类型的 System.Type 对象。 Type t typeof(int); GetType: Gets the Type of the current instance. 方法&#xff0c;获取当前实例的类型。 int i 10; Consol…