CLR之委托的揭秘(一)
初识委托:
在之前的学习中我们已经可以把对象,值,数组当作参数传递给方法,但是有没有可能把方法也当作参数传递给方法呢?有了这个想法于是就有了委托。方法当作一种参数去传递,但是方法有的有返回值有的没有返回值,这如何处理?委托又用在什么地方?通过这篇文章我们来学习一下委托的用法
委托解密:
在C#中要使用委托。必选先定义要使用的委托,在使用时需要创建该委托的一个或多个实例,以下示例展示了如何声明委托
/*
委托的安全性非常高,所以在声明委托时,要声明委托返回的类型和参数类型
*/
//声明返回类型为double 两个参数类型为long的委托
public delegate double TwolongsOp(long first,long second);
//声明返回类型为string 无参的委托
public delegate string Getstring();
//声明返回类型为void 参数类型为int的委托
public delegate void IntMethodInvoker(int x);
由于定义一个委托实际上是定义一个类,但这个类前面必须加上delegate关键字,所以委托可以定在类中的任何位置,也可以在名称空间中把委托当作顶层对象定义,表面上看,委托声明只需要一句话public delegate double TwolongsOp(long first,long second);,但从CLR角度来看,委托实际上是很复杂的,在使用委托之前先来看一下,底层是如何处理这一句话的。
编译器在读取这行代码时,实际上会自动为其生成一个完整的类,这个类中包含有一个构造器和Invoke,BeginInvoke,EndInvoke方法。自动生成的这个类继承自MulticastDelegate,所以这个类也继承了MulticastDelegate的字段,属性和方法。这个将在委托链中使用其中的一些方法。
那么经过CLR的自动编译以后,我们就可以开始使用委托,下面代码就是如何使用委托
class Program
{
//声明返回类型为string 无参的委托
public delegate string Getstring();
static void Main(string[] args)
{
int x = ;
//实例化委托,并且将int的ToString()方法当作参数传递给委托
Getstring getstring = new Getstring(x.ToString);
//语法糖:简化委托调用和使用new效果一样
Getstring getstring1 = x.ToString;
//调用委托方法
Console.WriteLine(getstring());
//CLR生成的类中就包含的方法安全调用
Console.WriteLine(getstring1.Invoke());
}
}
实际上代码中使用getstring()方法调用和使用Invoke()调用是相同的,因为getstring()方法是委托类型的一个变量,C#编译器会用getstring.Invoke()代替getstring(),如果为了减少输入量,只需要委托示例,就可以只传送地址,这称为委托判断。
委托链:
链式语法在C#中非常常见,Linq就是典型的链式方法调用,而委托也支持链式方法调用,委托链指的就是委托对象的集合,利用链式调用集合中的委托所代表的全部方法,但是委托链是有限制和缺点的,委托链中间方法的返回值会被丢弃无法获取,所以委托返回值最好是void,如果是带有返回值的,会返回最后一个方法的返回值。
举个例子,如果我委托别人帮我去拿一个快递,我又告诉他回来路上顺便帮我带份饭,这是两件事情,如果这两件事都只是去做,不需要拿到返回值,那么委托链可以满足,但是如果我要求两个方法,第一个方法要把快递返回到我手上,第二个方法饭也要返回到我手上,那么就无法获取第一个方法的返回值,也就是说我只能拿到饭,而拿不到快递。接下来看代码比较
//声明返回类型为string 无参的委托
public delegate string Getstring();
static void Main(string[] args)
{
//实例化委托链
Getstring getstatus = null;
//语法糖:支持+=/-=添加方法/移除方法
getstatus += TakeExpress;
getstatus += beltfood;
//获得结果
Console.WriteLine(getstatus());
}
//取快递方法,返回的string当作实体类型看
public static string TakeExpress()
{
return "你的快递是XX,已经为你取了";
}
//带饭方法,返回的string当作实体类型看
public static string beltfood()
{
return "为你带了一份黄焖鸡米饭";
}
两个方法最终只输出了最后一个方法的返回值,我们得到了一份黄焖鸡米饭,但是快递没有得到,于是我们修改以下以上代码,改为如下,可以看到两个方法都被执行了
//声明返回类型为string 无参的委托
public delegate void Getstring();
static void Main(string[] args)
{
//实例化委托链
Getstring getstatus = null;
//语法糖:支持+=/-=添加方法/移除方法
getstatus += TakeExpress;
getstatus += beltfood;
//获得结果
getstatus();
}
public static void TakeExpress()
{
Console.WriteLine("你的快递是XX,已经为你取了");
}
public static void beltfood()
{
Console.WriteLine("为你带了一份黄焖鸡米饭");
}
匿名委托:
匿名方法在.NET 中提高了 代码的可读性和优雅性。对于更多操作较少的方法直接写为匿名函数,这样会大大提高代码的可读性。这里有两个值得注意的地方: 第一,不能使用跳转语句跳转到该匿名方法外,第二 不能使用ref,out修饰的参数,下面是一个匿名委托的调用
//声明返回类型为string 无参的委托
public delegate string Getstring(string str);
static void Main(string[] args)
{
//直接在委托上完善方法
Getstring Spkeak = delegate (string str)
{
if (str == "哑巴")
{
return "我是哑巴,我不能说话";
}
return "我会说话";
}; Console.WriteLine(Spkeak("哑巴"));
小结:
委托是一种比较常用的函数回掉方法,常用于某种情况下触发委托。
CLR之委托的揭秘(一)的更多相关文章
- CLR之委托的揭秘(二)
杂谈 在开始真正的代码之前,分析一下上周的一些工作内容,发现自己在代码上还是有很多小毛病需要纠正和去更改的,首先之前一直疏于文档的整理,几乎很少去写文档,第二对于接口开发过程中缺少一定的严谨性,很多问 ...
- 大话C#之委托
开篇先来扯下淡,上篇博客LZ在结尾说这篇博客会来说说C#中的事件.但是当LZ看完事件之后发现事件是以委托为基础来实现的,于是LZ就自作主张地在这篇博客中先来说说委托,还烦请各位看官见谅!!!另外关于委 ...
- 通过委托来实现异步 Delegate的BeginInvoke和EndInvoke
什么是.net的异步机制呢? 解释这个话题之前,先让我们来看看同步执行的程序 https://github.com/chucklu/Test/blob/master/DotNet4.5开发指南/并行处 ...
- C#多线程之旅(1)——介绍和基本概念
原文地址:C#多线程之旅(1)——介绍和基本概念 C#多线程之旅目录: C#多线程之旅(1)——介绍和基本概念 C#多线程之旅(2)——创建和开始线程 C#多线程之旅(3)——线程池 C#多线程之旅( ...
- .NET本质论 方法
方法和JIT编译 CLR只执行本机的机器代码.如果一个方法体由CIL组成,那么它就必须在调用之前被转换为本机的机器码(将MSIL编译为本机代码,运行库提供了两种方式.一种就是在安装与部署时的预编译(由 ...
- Win7下VS2010、IIS7配置常见问题收集
一 在Win7下应按什么次序安装vs2010和iis7 win7推荐先安装iis7,再安装vs2010:如果次序反了,必须注册iis才可以用. IIS中ASP.NET的版本号此时可选的有1.1.2.0 ...
- C# 多线程系列(一)
线程是怎样工作的 1.多线程由一个线程调度器来进行内部管理,一个功能是CLR常常委托给操做系统. 一个线程调度器确保所有激活的线程在执行期间被合适的分配,等待或者阻塞的线程(比如,一个独占锁或者等待用 ...
- C#线程 入门
Threading in C# 第一部分: 入门 介绍和概念 C#支持通过多线程并行执行代码.线程是一个独立的执行路径,能够与其他线程同时运行.C#客户端程序(控制台,WPF或Windows窗体) ...
- [CLR via C#]17. 委托
回调函数是一种非常有用的编程机制,它已经存在很多年了.Microsoft .NET Framework通过委托(delegate)来提供一种回调机制.不同于其他平台(比如非托管C++)的回调机 ...
随机推荐
- Python实战之IO多路复用select实例
Select方法: 句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间) 参数: 可接受四个参数(前三个必须) 返回值 ...
- 简单的CSS颜色查看工具
可以通过输入ARGB(A代表透明度)格式或者HEX格式查看颜色,也可以进行ARGB格式和者HEX格式转换,如下图 使用C#编写,我已将源代码压缩上传 下载地址:http://files.cnblogs ...
- SQL SERVER 查看日志大小及日志已满的处理方法 (转)
--解决方法 --日志文件满而造成SQL数据库无法写入文件时,可用两种方法: --查看数据库日志大小 dbcc sqlperf(logspace) --清空日志. --1.打开查询分析器,输入命令 D ...
- CSS之 border 属性
特性 border-width 不支持百分比 border-color 默认颜色是 color border-color 透明值的作用:可利用增加可点击区域,利用内阴影做边框 border 应用 ...
- 微信开发-微信JSSDK错误:invalid url domain
错误类型:invalid url domain 调试返回参数: { "errMsg": "config:invalid url domain" } 截图: 环境 ...
- UVa10129,Play On Words
给出n个单词,如果一个单词的尾和另一个单词的头字符相等,那么可以相连,问这n个单词是否可以排成一列.欧拉路应用,构图:一个单词的头尾字母分别作为顶点,每输入一个word,该word的头指向word的尾 ...
- python中sys.exit()和os._exit(0)退出程序
python中退出程序的两种方法,0为默认状态,可以为空,两者均会退出当前运行的程序,os._exit(0)中的0不能省略 sys.exit(0):可以捕获SystemExit异常,然后做相应的清理工 ...
- Android SDK国内更新
恩,废话就不多说了,俩网址,mirrors.neusoft.edu.cn和ubuntu.buct.edu.cn,在这里感谢wecloud和北京化工大学,十分感谢提供方便之门
- java传值与传引用总结
基本数据类型 我们先来看一个代码 public class ParamTest { public static void main(String[] arge) { double percent = ...
- mybatis generator eclipse插件的安装
mybatis generator 可以提高开发速度,这个插件可以自动生成代码,创建DAO层相关代码,就像利用HIbernate反相生成一样,安装前可以先到百度网盘下载: 文件:MyBatisGene ...