CLR之委托的揭秘(二)
杂谈
在开始真正的代码之前,分析一下上周的一些工作内容,发现自己在代码上还是有很多小毛病需要纠正和去更改的,首先之前一直疏于文档的整理,几乎很少去写文档,第二对于接口开发过程中缺少一定的严谨性,很多问题没有考虑清楚就已经代码敲完了,其实应该先针对接口去写一份接口说明文档,一方面提升自己的文档能力,另外一方面也通过文字整理自己的思路,还有就是程序开发中不能懒,因为懒已经出了很多问题,程序毕竟是严谨的,你忽能它,它也必然忽能你!
这是上周工作中的一些总结,接下来继续以CLR的角度分析委托,上一节说了委托的定义,委托链,还有匿名委托。接下来我们分析
泛型委托
其实我对于泛型委托之前也是完全一知半解,有一次在用Linq的时候,先用了Where有用了Find,我的本意是先筛选在查找,但实际上两者基本上是一回事,都是泛型委托,当然关于泛型委托不得不说的就是 Action<T> 泛型委托, Func<T, TResult>,两者是有区别的
Action<T> 泛型委托:封装一个方法,该方法只采用一个参数并且不返回值。可以使用此委托以参数形式传递方法,而不用显式声明自定义的委托。该方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并且不能返回值。当然泛型委托不只是只能支持一个参数,它最多可以支持四个参数。
Func<T, TResult> 委托:封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。同理,这里的泛型委托只是接受一个参数的委托,它最多同样支持四个参数。TResult:此委托封装的方法的返回值类型。
Action T
还记得上一篇文章中我们关于委托的定义和声明中,是如何要求的么?委托的安全性非常高,所以在声明委托时,要声明委托返回的类型和参数类型,但是在 Action<T> 上,我们不需要如此,接下来看一下普通声明和Action<T> 声明的委托有什么不同
/*
泛型委托和普通委托的声明对比
1.不需要使用delegate关键字
2.Action只能使用返回值为void的方法,如果返回值具有对象类型则报错
*/
delegate void DisplayMessage(string message);
static void Main(string[] args)
{ DisplayMessage messageTarget;
messageTarget = ShowWindowsMessage;
messageTarget("Hello, World!"); Action<string> messageTarget1;
messageTarget1 = ShowWindowsMessage;
messageTarget1("泛型委托");
}
public static void ShowWindowsMessage(string s) {
Console.WriteLine(s);
}
我在注释里加入了一行解释:不需要使用delegate关键字,为什么 Action<T> 可以直接声明使用呢?这和其自身封装有关,下面代码就是其在系统中的封装,可以看出来,Action在元数据中就已经存在了public delegate void封装,明确了其使用的范围
//
// 摘要:
// 封装一个方法,该方法只有一个参数并且不返回值。
//
// 参数:
// obj:
// 此委托封装的方法的参数。
//
// 类型参数:
// T:
// 此委托封装的方法的参数类型。此类型参数是逆变。即可以使用指定的类型或派生程度更低的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。
public delegate void Action<in T>(T obj);
Func<T, TResult>
关于Func<T, TResult> 委托,和 Action<T> 委托的区别最大点在于Func<T, TResult>支持返回类型,刚才我们看了 Action<T> 以后会觉得 Action<T> 只能用于void方法,那么如果方法返回int, Action<T> 是不是就不能用了?对的,不能用了。
Func<T,TResult> 的表现形式分为以下几种:
1。Func<T,TResult>
2。Func<T,T1,TResult>
3。Func<T,T1,T2,TResult>
4。Func<T,T1,T2,T3,TResult>
5。Func<T,T1,T2,T3,T4,TResult>
其实以上的几种表现形式就是Func<T,TResult>的几种重载,最多支持四个参数的重载,分别说一下各个参数的意义,TResult表示 委托所返回值 所代表的类型, T,T1,T2,T3,T4表示委托所调用的方法的参数类型,
以下是使用示例:
/*
使用普通委托和泛型委托同样完成一个返回值为string,参数为int方法的委托调用
*/
delegate string DisplayMessage(int message);
static void Main(string[] args)
{
DisplayMessage messageTarget;
messageTarget = Kuadi;
Console.WriteLine(messageTarget());
//Func<T,TResult>
Func<int,string> messageTarget1;
messageTarget1 = Kuadi;
Console.WriteLine(messageTarget1());
}
public static string Kuadi(int zhong) {
if (zhong == )
return "你的快递";
else
return "没有你的货";
}
可以看的出来,泛型委托实际上比起普通委托最大好处就是可以少些很多代码,在以后的代码中可以用泛型委托完成的就不需要使用普通委托去完成,刚才文章中提到了一个委托在linq中得使用,那么linq中如何体现的Action<T> 泛型委托和 Func<T, TResult>泛型委托的呢
Linq中的泛型委托使用
namespace System.Linq
{
public static class Enumerable
{
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
}
}
由于Linq中的方法实在有点多,今天我们只看一下Where,当然具体实现是看不到,但是我们在这串代码中却看到了一个身影Func<TSource, bool>这实际上涉及了linq的内部另一个方法的调用,这串代码所做的事就是把条件作为一个参数传给predicate调用其内部方法,最终返回一个bool值。
当然了委托用在Liqn中不只是这么一个地方,还有很多地方都用到了委托,感兴趣的小伙伴可以研究一下,委托在LInq中的使用
CLR之委托的揭秘(二)的更多相关文章
- CLR之委托的揭秘(一)
初识委托: 在之前的学习中我们已经可以把对象,值,数组当作参数传递给方法,但是有没有可能把方法也当作参数传递给方法呢?有了这个想法于是就有了委托.方法当作一种参数去传递,但是方法有的 ...
- 解密jQuery事件核心 - 委托设计(二)
第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...
- C++模拟C#事件委托机制(二)
原文 来自于http://www.cnblogs.com/netssfy/archive/2010/02/02/1662056.html 为了解决非法地址访问的冲突,首先需要知道发生该错误的原因是什么 ...
- CLR via C#读书笔记二:类型基础
1.CLR允许将对象转换为它的(实际)类型或者它的任何基类型. 2.is操作符检测对象是否兼容于指定类型,is操作符永远不抛出异常. 3.as操作符返回对同一个对象的非null引用.如果对象不兼容,a ...
- C#编程之委托与事件四(二)【转】
C#编程之委托与事件(二) 我在上一篇文章(C#编程之委托与事件(一) )中通过示例结合的方法介绍了委托,在本文中,我同样以代码示例的方式来介绍C#里的事件机制. 二.事件 1.了解概 ...
- 转载——CLR标量函数、表值函数和聚合函数(UDA)
本节主要介绍使用CLR创建标量函数,表值函数和聚合函数. 所谓标量函数指的就是此函数只返回一个值.表值函数返回值是一个表.聚合函数是在select语句中使用的,用来聚合一个结果集,类似于Sum()或是 ...
- .NET基础拾遗(4)委托和事件1
一.委托初窥:一个拥有方法的对象 (1)本质:持有一个或多个方法的对象:委托和典型的对象不同,执行委托实际上是执行它所“持有”的方法. (2)如何使用委托? ①声明委托类型(delegate关键字) ...
- ios协议和委托
在iPhone开发协议和委托是常接触到的东西,到底什么是协议什么是委托,他们什么关系? 一 协议 (1)协议相当于没有与类相关联的接口,他申明一组方法,列出他的参数和返回值,共享给其他类使用,然后不进 ...
- 大话C#之委托
开篇先来扯下淡,上篇博客LZ在结尾说这篇博客会来说说C#中的事件.但是当LZ看完事件之后发现事件是以委托为基础来实现的,于是LZ就自作主张地在这篇博客中先来说说委托,还烦请各位看官见谅!!!另外关于委 ...
随机推荐
- akka tips
1.actorSelection,当涉及actor远程通信时,可以使用actorSelection. context.actorSelection("akka.tcp://app@other ...
- Scala 运算符和集合转换操作示例
Scala是数据挖掘算法领域最有力的编程语言之一,语言本身是面向函数,这也符合了数据挖掘算法的常用场景:在原始数据集上应用一系列的变换,语言本身也对集合操作提供了众多强大的函数,本文将以List类型为 ...
- Android的快速开发框架 afinal
afinal 框架学习: http://www.oschina.net/p/afinal
- 使用phpExcel导出excel时,报500错
在自己本地导出excel没有问题,但是放到服务器出现500的错误! 解决方法:查看控制器引用的header文件,是否包含空格,如下: header('Pragma:public'); ...
- ubuntu tftp-server 服务器安装与配置
第一步:安装tftp服务sudo apt-get install tftpd tftp openbsd-inetd第二步:目录配置vi /etc/inetd.conf修改文件夹为根目录下的tftpbo ...
- redis数据类型和应用场景
Redis是什么?两句话可以做下概括: 1. 是一个完全开源免费的key-value内存数据库 2. 通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings.map. list ...
- 再识QT(1)
2015年的时候开始接触QT,自学了1个月,由于没有项目驱动,也没人指导,最终还是撇下了,水平也仅限于拖拖控件,做一些简单的界面,对QT的内部机制完全是懵逼的.时隔两年,最近由于公司项目需要使用QT, ...
- 谢欣伦 - 原创教程 - 使用GDI+绘制抗锯齿斜线
早些年用过GDI的同学都知道,用GDI绘图API函数画斜线那个锯齿有多恶心.就像下图第一行的三条斜线: 坦白说,45度斜线在抗锯齿以前还是蛮抗锯齿的,哈哈,抗不抗都没什么差别. 那第二行很自然就看得出 ...
- 如何利用Oracle VM Templates 在几分钟内部署Oracle Real Application Clusters (RAC)
本文未经授权,禁止一切形式的转载.如果对本文有任何疑问可以通过以下方式和我交流: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiang ...
- 聊聊 Material Design 里,阴影的那些事儿!
当你的设计师要求你在某个 View 上增加阴影效果,那你只需要认真阅读本文,阴影的问题就不再是问题. 一.前言 设计师的世界,与常人不同,有时候想要扁平化的风格,有时候又想要拟物化的风格.而在 Mat ...